使用具有多个比较器的比较器



我可以使用此代码中的所有简单比较器来进行精细排序,但不能对ComplexComparator进行排序。我不知道如何编码才能使其正常工作。如有任何建议/解释,不胜感激。

这是我的主要程序:

package pkgTest;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Student[] students = new Student[6];
students[0] = new Student("Pete", 1989, 3.6);
students[1] = new Student("Tomas", 1989, 3.9);
students[2] = new Student("Helen", 1990, 3.6);
students[3] = new Student("Steve", 1991, 3.7);
students[4] = new Student("Natalie", 1993, 3.7);
students[5] = new Student("John", 1992, 4.0);
NameComparator byName
= new NameComparator();
BirthDateComparator byBirthDate
= new BirthDateComparator();
AverageComparator byAverage
= new AverageComparator();
ComplexComparator complexSorting
= new ComplexComparator(byName,
byAverage);
System.out.println("===============");
System.out.println("Before sorting:");
System.out.println("===============");
for (Student student : students) {
System.out.println(student.getName()
+ " // " + student.getBirthDate()
+ " // " + student.getAverage());
}
Arrays.sort(students, complexSorting);
System.out.println("==============");
System.out.println("After sorting:");
System.out.println("==============");
for (Student student : students) {
System.out.println(student.getName()
+ " // " + student.getBirthDate()
+ " // " + student.getAverage());
}
}
}

以下是其他类:

package pkgTest;
public class Student {
private String name;
private int birthDate;
private double average;
public Student(String name, int birthDate,
double average) {
this.name = name;
this.birthDate = birthDate;
this.average = average;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getBirthDate() {
return this.birthDate;
}
public void setBirthDate(int birthDate) {
this.birthDate = birthDate;
}
public double getAverage() {
return this.average;
}
public void setAverage(double average) {
this.average = average;
}
}

package pkgTest;
import java.util.Comparator;
public class ComplexComparator implements Comparator<Student> {
public ComplexComparator(Comparator<Student> one,
Comparator<Student> another) {
}
@Override
public int compare(Student one, Student another) {
/*This is the part that
I just couldn't figure
it out to get it work.
It has to work no matter
which 2 of the 3 comparators
I use to set the input
parameters of ComplexComparator.
I have to make it work by
modifying only this part of
the code.*/
}
}

package pkgTest;
import java.util.Comparator;
public class AverageComparator implements Comparator<Student> {
@Override
public int compare(Student one, Student another) {
if (one.getAverage()
< another.getAverage()) {
return -1;
} else if (one.getAverage()
== another.getAverage()) {
return 0;
} else {
return +1;
}
}
}
package pkgTest;
import java.util.Comparator;
public class BirthDateComparator implements Comparator<Student> {
@Override
public int compare(Student one, Student another) {
if (one.getBirthDate()
< another.getBirthDate()) {
return -1;
} else if (one.getBirthDate()
== another.getBirthDate()) {
return 0;
} else {
return +1;
}
}
}

package pkgTest;
import java.util.Comparator;
public class NameComparator implements Comparator<Student> {
@Override
public int compare(Student one, Student another) {
return one.getName().
compareToIgnoreCase(another.getName());
}
}

您必须按照以下方式修改类ComplexComparator,至少。。。

import java.util.Comparator;
public class ComplexComparator implements Comparator<Student> {
private Comparator<Student> comparatorOne;
private Comparator<Student> comparatorTwo;
public ComplexComparator(Comparator<Student> one,
Comparator<Student> another) {
this.comparatorOne = one;
this.comparatorTwo = another;
}
@Override
public int compare(Student one, Student another) {
// make a first comparison using comparator one
int comparisonByOne = comparatorOne.compare(one, another);
// check if it was 0 (items equal in that attribute)
if (comparisonByOne == 0) {
// if yes, return the result of the next comparison
return comparatorTwo.compare(one, another);
} else {
// otherwise return the result of the first comparison
return comparisonByOne;
}
}
}

对于两个以上的Comparator,您将需要其中的一个List(或另一个重载构造函数(和一个保持特定比较顺序的循环。

编辑

对于您关于分拣订单的额外要求,这可能会有所帮助:

public class ComplexComparator implements Comparator<Student> {
private Comparator<Student> comparatorOne;
private Comparator<Student> comparatorTwo;
private boolean orderOneAscending = true;
private boolean orderTwoAscending = true;
/**
* Constructor without any sort orders
* @param one   a comparator
* @param another   another comparator
*/
public ComplexComparator(Comparator<Student> one, Comparator<Student> another) {
this.comparatorOne = one;
this.comparatorTwo = another;
}
/**
* Constructor that provides the possibility of setting sort orders 
* @param one   a comparator
* @param orderOneAscending sort order for comparator one 
*      (true = ascending, false = descending)
* @param another   another comparator
* @param orderTwoAscending sort order for comparator two
*      (true = ascending, false = descending)
*/
public ComplexComparator(Comparator<Student> one, boolean orderOneAscending,
Comparator<Student> another, boolean orderTwoAscending) {
this.comparatorOne = one;
this.comparatorTwo = another;
this.orderOneAscending = orderOneAscending;
this.orderTwoAscending = orderTwoAscending;
}
@Override
public int compare(Student one, Student another) {
int comparisonByOne;
int comparisonByAnother;
if (orderOneAscending) {
/*  note that your lexicographical comparison in NameComparator 
returns a negative integer if the String is greater!
If you take two numerical Comparators, the order will
turn into the opposite direction! */
comparisonByOne = comparatorOne.compare(another, one);
} else {
comparisonByOne = comparatorOne.compare(one, another);
}
if (orderTwoAscending) {
comparisonByAnother = comparatorTwo.compare(one, another);
} else {
comparisonByAnother = comparatorTwo.compare(another, one);
}
if (comparisonByOne == 0) {
return comparisonByAnother;
} else {
return comparisonByOne;
}
}
}

只需摆弄这些值并尝试一些修改,就可以熟悉有关比较和排序的常见问题。我希望这会有所帮助。。。

修改您的ComplexComparator如下

public class ComplexComparator implements Comparator<Student> {
private List<Comparator<Student>> listComparators;
@SafeVarargs
public ComplexComparator(Comparator<Student>... comparators) {
this.listComparators = Arrays.asList(comparators);
}
@Override
public int compare(Student studen1, Student studen2) {
for (Comparator<Student> comparator : listComparators) {
int result = comparator.compare(studen1, studen2);
if (result != 0) {
return result;
}
}
return 0;
}
}

这里有一个通用的复杂比较器,可以用于任何类型的对象(基于这个答案(:

public class ComplexComparator<T> implements Comparator<T> {
private List<Comparator<T>> listComparators;
@SafeVarargs
public ComplexComparator(Comparator<T>... comparators) {
listComparators = Arrays.asList(comparators);
}
@Override
public int compare(T o1, T o2) {
for (Comparator<T> comparator : listComparators) {
int result = comparator.compare(o1, o2);
if (result != 0) {
return result;
}
}
return 0;
}
}

当您使用它时,会有一个未选中的强制转换警告,但您可以取消它,因为只要您的类具有可比性,它就会成功强制转换。

@SuppressWarnings("unchecked")
Comparator<MyClass> comparator = new ComplexComparator(
MyClass.ComparatorA,
MyClass.ComparatorB);
Collections.sort(mySet, comparator);

如果有人知道如何避免收到警告,请发表评论,我会更新答案。

我不确定您希望如何呈现解决方案。但根据我的理解,如果你想把代码放在注释的地方,你可以试着这样放代码。

假设在比较完名称后的情况下,若相同,则打算移动到平均值。

public int compare(Student StOne, Student StAnother) {
if(one.compare(Sone, Sanother)==0) {
return another.compare(StOne, StAnother);
}
else 
return one.compare(StOne, StAnother);
}

但为此,您需要确保在ComplexComparator的构造函数中获取的值(byName,byAverage(应该是该类的实例变量,并且需要在构造函数中初始化。

public class ComplexComparator implements Comparator<Student> {
private Comparator<Student> one; 
private Comparator<Student> another;
public ComplexComparator(Comparator<Student> one,
Comparator<Student> another) {
this.one=one;
this.another=another;
}
@Override
public int compare(Student one, Student another) {
//code given above
} }

相关内容

  • 没有找到相关文章

最新更新