[英]Java PriorityQueue Comparator to insert a 2D array under certain conditions
[英]Sorting an array in java with certain conditions
我有一类叫做“运动员”的类,它是人类的一个副类。 在“人”类中,我实现了可比较的界面,并使用compareTo方法来比较不同运动员的年龄。 在运动员课中,我还有一个名为Year的字段,它对应于运动员开始比赛的年份。 在我程序的主要方法中,我有一个添加运动员和人类的数组列表。 我希望,如果运动员的年龄与开始比赛的年份相同。 我使用instanceof来检查班级实例中的实例是否是运动员类型的对象,但此后我不知道如何使其工作。
public int compareTo(Human other)
{
if(this instanceof Athlete && other instanceof Athlete && this.age == other.age){
return ;
}
return this.age - other.age;
}
}
使用多态性 ,而不是运算符instanceof
。
即:重载Athlete类中的compareTo方法。
public int compareTo(Athlete other) {
//This method will be invoked if and only if you compare an athlete with another athlete
}
另外,请考虑equals方法的结果应与compareTo方法的结果一致。
一种可能的解决方案是在Athlete
类中也添加一个compareTo
方法,其内容如下(需要重写,因为很久以前我一直没有从事Java的工作):
public int compareTo(Athlete other){
int result = super.compareTo((Human)other);
if(result == 0){
return this.year - other.year;
}
return result;
}
作为代码审查,我想说完整的代码应类似于以下内容:
人的java
public int compareTo(Human other){
return age - other.age;
}
Athlete.java
@Override
public int compareTo(Human other){
if(other instanceof Athlete){
return compareTo((Athlete)other);
}
return super.compareTo(other);
}
public int compareTo(Athlete other){
int result = super.compareTo((Human)other);
if(result == 0){
return this.year - other.year;
}
return result;
}
使用您的示例,您也可以只比较年份:
public int compareTo(Human other)
{
if(this instanceof Athlete && other instanceof Athlete && this.age == other.age){
String tYear = ((Athlete)this).getYear();
String oYear = ((Athlete)other).getYear();
int tYearInt = 0;
int oYearInt = 0;
try {
tYearInt = Integer.parseInt(tYear);
oYearInt = Integer.parseInt(oYear);
} catch (Exception e){
e.printStackTrace();
}
return tYearInt - oYearInt;
}
return this.age - other.age;
}
但是,话虽如此,请随时考虑@Andres答案,无论何时使用instanceof,都应质疑您的设计是否错误。
就像安德列斯(Andres)所说的,使用多态。 这样做的方法如下:
首先,在“ Human
类中this instanceof Athlete
不是好的样式,因为从“ Human
类的角度来看,“ Athlete
是一个子类,而引用子类在某些情况下会导致问题。 而是,将另一个compareTo()
方法放入Athlete
类。 如果Athlete.compareTo()
被调用,你已经知道, this
是类型的Athlete
,如果你要比较的year
场,你只需要检查other instanceof Athlete
,这是确定的,因为现在我们是在透视Athlete
类,从这里开始, Athlete
不是子类。
就是说,在Athlete
课程中,使用以下命令:
public int compareTo(Human other) {
int humanComp = super.compareTo(other);
if (humanComp != 0){
return humanComp;
}
if (other instanceof Athlete) {
return ((Athlete)other).year - this.year;
}
return 0;
}
该解决方案首先使用Human.compareTo()
(与super.compareTo(other)
一起super.compareTo(other)
)来检查Human
类是否已经知道如何对this
和other
实例进行排序。 如果不是,即该调用返回0,则必须继续比较更多详细信息,在本例中为year
字段。
因为我们使用了Human.compareTo()
,所以我们必须确保它存在于Human
类中并且可以正常工作:
public int compareTo(Human other) {
return this.age - other.age;
}
这只是按age
进行比较,因为这是Human
类中我们知道可用于比较的唯一字段。
compareTo
的文档说:
最后,实现者必须确保对于所有
z
,x.compareTo(y)==0
意味着sgn(x.compareTo(z)) == sgn(y.compareTo(z))
。
您提出的方法不符合此要求。 例如,假设
x = Athlete, age = 35, start date = 2000
y = Human, age = 35
z = Athlete, age = 35, start date = 2001
在这个例子中
x.compareTo(y) == 0 // y is not an athlete
x.compareTo(z) < 0 // Both athletes, different start dates.
y.compareTo(z) == 0 // y is not an athlete
如果您不遵守Comparable
的合同,则未指定Arrays.sort
或Collections.sort
的行为。 理想情况下,您会得到一个异常,但是麻烦的是,这些排序方法根据数组或列表的大小使用不同的算法,并且如果输入数组或列表包含以下内容 ,则您更有可能因不正确的compareTo
方法而引发异常大量的要素 。 这意味着您应该使用随机生成的长数组非常仔细地测试您的compareTo
方法,否则,您的代码中可能会包含难以发现的细微错误。
正确的compareTo
方法如下所示:
public int compareTo(Human other) {
int result = Integer.compare(age, other.age);
if (result != 0)
return result;
if (!(this instanceof Athlete))
return other instanceof Athlete ? -1 : 0;
return other instanceof Athlete
? Long.compare(((Athlete) this).startDate(), ((Athlete) other).startDate())
: 1;
}
该方法首先按年龄排序。 如果两个人的年龄相同,则按类型将其排在第一位(运动员排在第一位)。 年龄相同的运动员按开始日期排序。 具有相同年龄的非运动员不会以任何特定顺序出现。
最后,请注意,通常最好使用多态性而不是instanceof
。 这里的问题是Human implements Comparable<Human>
。 因此compareTo
方法必须接受一个Human
而不是一个Athlete
。 即使您在Athlete
重写compareTo
,该参数也必须是Human
,并且无论如何您都必须使用instanceof
来检查参数的类型(如@GentianKasa的回答), 或者编写一个完全独立的方法compareToAthlete(Athlete athlete)
渗漏compareToAthlete(Athlete athlete)
和在Athlete
执行以下操作
@Override
public int compareTo(Human human) {
return -human.compareToAthlete(this); // Note the minus sign!
}
compareToAthlete
也将需要两个版本。 在此有效的同时,这意味着compareTo
方法的逻辑分布在四种方法中,这使得更难于推理其正确性。 在这种情况下,我会nose之以鼻并使用instanceof
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.