0

我有一个简单的类,其中包含一个字符串(名称)和一个整数(年龄)。应存储在集合中的对象不得具有双重名称值,并且应按年龄降序排序。第一个代码示例删除所有双名,但不包含第二个排序标准:

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;                  
    } 

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

4

1 回答 1

3

您在这里有一个基本问题:您希望同时测试唯一性排序条目。没有内置集合可以同时检查条目是否相等并且它们的比较是否为 0。

例如,两个Set实现是HashSetand TreeSet

  • HashSet使用Object's .equals()/.hashCode()来测试是否相等;
  • TreeSet使用 a 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.

要获得已排序的人员列表,您必须将此地图的副本.values()作为列表并使用Collections.sort(). 如果你使用 Guava,后半部分就像Ordering.natural().sortedCopy(theMap.values()),只要你的值实现Comparable

于 2013-06-06T10:10:41.707 回答