java comparator:两个排序标准

o2rvlv0m  于 2021-06-30  发布在  Java
关注(0)|答案(1)|浏览(131)

我有一个简单的类,它包含一个字符串(name)和一个整数(age)。应存储在集合中的对象不得具有双重名称值,并应按年龄递减排序。第一个代码示例将删除所有双代号,但不包含第二个排序条件:

public int compare(Person p1, Person p2) {  
    int reVal = 1;

       if(p1.getName().compareTo(p2.getName()) != 0){
       reVal = 1;       
       }
       else {
       reVal = 0;       
       }                               
         return reVal;                  
    }

下一个比较器示例将对不包含任何双重名称的其余对象集进行排序:

public int compare(Person p1, Person p2) {  
    boolean ageGt = (p1.getAge() > p2.getAge());
    int reVal = 1;

       if(p1.getName().compareTo(p2.getName()) != 0){
       if(scoreGt)
            reVal = -1;
       else 
            reVal = 1;      
       }
       else {
       reVal = 0;       
       }                               
         return reVal;                  
    }

第二个比较器根据对象的年龄值正确地对它们进行排序,但是它允许使用双名称,我不明白这一点,因为outer if语句已经检查了两个对象的名称是否相等。为什么会这样?

pengsaosao

pengsaosao1#

这里有一个基本问题:您需要同时测试单一性和排序条目。没有一个内置集合将同时检查条目是否相等以及它们的比较是否为0。
例如,两个 Set 实现是 HashSet 以及 TreeSet : HashSet 使用 Object.equals() / .hashCode() 检验是否相等; TreeSet 使用 Comparator (或对象的 Comparable 测试平等性的能力。
这不是一回事。实际上,对于一个特定的jdk类, BigDecimal ,这可能会让人大吃一惊:

final BigDecimal one = new BigDecimal("1");
final BigDecimal oneDotZero = new BigDecimal("1.0");

final Set<BigDecimal> hashSet = new HashSet<>();
// BigDecimal implements Comparable of itself, so we can use that
final Set<BigDecimal> treeSet = new TreeSet<>();

hashSet.add(one);
hashSet.add(oneDotZero);
// hashSet's size is 2: one.equals(oneDotZero) == false

treeSet.add(one);
treeSet.add(oneDotZero);
// treeSet's size is... 1! one.compareTo(oneDotZero) == 0

你不能既有蛋糕又吃。在这里,你要根据名字来测试单一性,根据年龄来比较,你必须使用 Map .
为了得到一份已排序的人员名单,你必须复印一份这张Map上的人员名单 .values() 作为列表和使用 Collections.sort() . 如果你用Guava,这后一部分是一样简单的 Ordering.natural().sortedCopy(theMap.values()) ,前提是实现您的价值观 Comparable .

相关问题