为什么我们需要 List 使用 Collection.sort() 方法进行排序?

Why do we need List to sort using Collection.sort() method?

我打算从哈希图中对键进行排序。我正在使用自定义排序方法。

以下代码在我使用 Set 的 compareTo() 方法上给出 compile-time 错误 作为 Collection

Set<String> set = map.keySet();
Collections.sort(set, (a, b) -> map.get(a) == map.get(b) ?  a.compareTo(b) : map.get(b) - map.get(a));

如果我将 Set 转换为 List 然后排序,那么一切 都可以正常工作

List<String> words = new ArrayList<>(map.keySet());
Collections.sort(words, (a, b) -> map.get(a) == map.get(b) ?  a.compareTo(b) : map.get(b) - map.get(a));

我需要转换为 List 来对 collection 进行排序的原因是什么?为什么我不能使用 Set 进行排序?

一个Set没有API改顺序。如果你尝试,你会注意到自己,例如交换 Set.

的第一个和第二个元素

此外,集合有自己的关于顺序的合同,如果您可以从外部更改它,就会违反该顺序

  • HashSet和一个HashMap的key集合根本不保持顺序。如果没有指定其他合约,这是集合的一般假设
  • LinkedHashSetLinkedHashMap 的键集将反映插入顺序
  • TreeSetTreeMap 的键集使用键的自然顺序或明确指定的比较器的顺序。 SortedSet 的所有实现都绑定到 Comparator 或键的自然顺序。

为了对某些东西进行排序,您需要一个集合来维护顺序并具有 API 支持更改顺序。

A List 是天生的候选人。您还可以对数组进行排序。由于 LinkedHashMap 反映了插入顺序,您可以通过按所需顺序添加元素来创建具有特定顺序的 LinkedHashMap

map = map.entrySet().stream()
    .sorted(Map.Entry.<String,Integer>comparingByValue().reversed()
                     .thenComparing(Map.Entry::getKey))
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                              (a,b)->b, LinkedHashMap::new));

此外,你的比较器看起来坏了。术语 map.get(b) - map.get(a) 表示值是数字,在上面的示例中我假设 Integer,但是 map.get(a) == map.get(b) 比较了装箱对象的 references

而在 Integer 的情况下,差异 map.get(b) - map.get(a) 可能会溢出。您应该改用 Integer.compare(map.get(b), map.get(a)

或者在适用的情况下使用比较器的工厂方法

List<String> words = new ArrayList<>(map.keySet());
words.sort(Comparator.<String>comparingInt(map::get).reversed()
                     .thenComparing(Comparator.naturalOrder()));

根据 Java 中的定义,Set 不是有序集合。

我们无法通过调用 Set 上的 Collections.sort() 方法对 Java Set 集合进行排序。

不直接支持对 Java 中的集合进行排序。要对集合进行排序,请按照以下步骤操作:

  • 将集合转换为列表。
  • 使用 Collections.sort() API.
  • 对列表进行排序
  • 将列表转换回集合。

我们可以使用集合的排序实现。

根据下图HashSet,LinkedHashSet,TreeSet 是 Set.

的实现
  • HashSet:无序
  • LinkedHashSet: 插入顺序
  • TreeSet:有序(自然顺序,即字母、字母数字或时间顺序)

注意:HashSet 是大多数情况下使用的默认实现。

图表参考:https://dzone.com/articles/an-introduction-to-the-java-collections-framework