Java comparator: Two ordering criteria

前端 未结 1 1789
悲&欢浪女
悲&欢浪女 2020-12-22 06:00

I have a simple class that contains a string (name) and an integer (age). The objects, that shall be stored in the collection, must not have double name values and shall be

1条回答
  •  囚心锁ツ
    2020-12-22 06:23

    You have a fundamental problem here: you want at the same time to test for unicity and to order entries. There is no builtin collection which will check at the same time that entries are equal and that their comparison is 0.

    For instance, two Set implementations are HashSet and TreeSet:

    • HashSet uses Object's .equals()/.hashCode() to test for equality;
    • TreeSet uses a Comparator (or the objects' Comparable capability if they implement it) to test for equality.

    This is not quite the same thing. In fact, with one particular JDK class, that is, BigDecimal, this can get quite surprising:

    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
    

    You cannot both have your cake and eat it. Here, you want to test unicity according to the name and comparison according to the age, you must use a Map.

    As to obtain a sorted list of persons, you will have to do a copy of this map's .values() as a list and use Collections.sort(). If you use Guava, this latter part is as simple as Ordering.natural().sortedCopy(theMap.values()), provided your values implement Comparable.

    0 讨论(0)
提交回复
热议问题