Java比较器:两个排序标准

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

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语句已被检查。 为什么会这样?

这里有一个根本问题:您希望同时测试unicity 订购条目。 没有内置集合可以同时检查条目是否相等以及它们的比较是0。

例如,两个Set实现是HashSetTreeSet

  • HashSet使用Object.equals() / .hashCode()来测试相等性;
  • TreeSet使用Comparator (或对象的Comparablefunction,如果它们实现它)来测试相等性。

这不是一回事。 事实上,对于一个特定的JDK类,即BigDecimal ,这可能会非常令人惊讶:

 final BigDecimal one = new BigDecimal("1"); final BigDecimal oneDotZero = new BigDecimal("1.0"); final Set hashSet = new HashSet<>(); // BigDecimal implements Comparable of itself, so we can use that final Set 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 

你不能两个都吃蛋糕吃。 在这里,你想根据年龄根据名称和比较来测试unicity,你必须使用Map

要获得一个排序的人员列表,您必须将此映射的.values()副本作为列表并使用Collections.sort() 。 如果你使用Guava,后一部分就像Ordering.natural().sortedCopy(theMap.values())一样简单,只要你的值实现Comparable