为什么我们需要 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集合根本不保持顺序。如果没有指定其他合约,这是集合的一般假设
LinkedHashSet
和LinkedHashMap
的键集将反映插入顺序
TreeSet
和 TreeMap
的键集使用键的自然顺序或明确指定的比较器的顺序。 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
我打算从哈希图中对键进行排序。我正在使用自定义排序方法。
以下代码在我使用 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集合根本不保持顺序。如果没有指定其他合约,这是集合的一般假设LinkedHashSet
和LinkedHashMap
的键集将反映插入顺序TreeSet
和TreeMap
的键集使用键的自然顺序或明确指定的比较器的顺序。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