【问题标题】:Why do we need List to sort using Collection.sort() method?为什么我们需要 List 使用 Collection.sort() 方法进行排序?
【发布时间】:2020-05-11 04:53:29
【问题描述】:

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

以下代码在 compareTo() 方法上给了我编译时错误,我使用 Set 作为集合

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 来对集合进行排序的原因是什么?为什么我不能使用 Set 排序?

【问题讨论】:

    标签: java sorting lambda collections compareto


    【解决方案1】:

    Set 没有用于更改顺序的 API。如果你尝试,你会注意到自己,例如交换Set 的第一个和第二个元素。

    此外,套装有自己的关于订单的合同,如果你可以从外部更改它就会被违反

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

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

    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) 比较了装箱对象的引用

    如果是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()));
    

    【讨论】:

      【解决方案2】:

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

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

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

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

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

      根据下图HashSetLinkedHashSetTreeSet是Set的实现。

      • HashSet: 无序
      • LinkedHashSet:广告订单
      • TreeSet:有序(自然顺序,即字母、字母数字或时间顺序)

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

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

      【讨论】:

        猜你喜欢
        • 2022-12-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多