如何在Java 8 Stream中定义自定义排序比较器以比较键和值

Har*_*ris 7 java lambda comparator java-8 java-stream

我想使用Java 8流对地图进行排序,并返回其键的列表。

地图签名为:

Map<Integer, Integer> ranks = new HashMap<Integer, Integer>();
Run Code Online (Sandbox Code Playgroud)

数据将类似于[1 = 6,5 = 13,2 = 11]

我必须在两个条件下对键进行排序并返回键列表。

  1. 如果键的所有值都不相同,则按降序排序并返回基于列表的值,例如

    input [1=6 , 5=13 , 2= 11 , 4 = 14 ]
    result [4,5,2,1]
    
    Run Code Online (Sandbox Code Playgroud)
  2. 如果键的两个或多个值具有相同的等级,则以升序返回这些相似的值,而项的其余部分相对于它们的值则按降序排列

    input [2=6 , 5=13 , 1= 11 , 3=13 ,9 = 22 ] result [9,3,5,1,2]
    
    Run Code Online (Sandbox Code Playgroud)

以下是适用于条件1,但不适用于条件2的代码段。

List<Integer> ranksList = ranks.entrySet().stream()
    .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
    .map(Map.Entry::getKey)
    .limit(k)
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

Ole*_*.V. 6

声明Comparator使用thenComparing的链接。

Comparator<Map.Entry<Integer, Integer>> entryComparator
            = Map.Entry.<Integer, Integer>comparingByValue(Comparator.reverseOrder())
                                         .thenComparing(Map.Entry.comparingByKey());

Map<Integer,Integer> ranks = Map.of(2, 6, 5, 13, 1, 11, 3, 13, 9, 22);

List<Integer> ranksList= ranks.entrySet().stream()
            .sorted(entryComparator)
            .map(Map.Entry::getKey).limit(47)
            .collect(Collectors.toList());

System.out.println(ranksList);
Run Code Online (Sandbox Code Playgroud)

输出是所需的:

[9,3,5,1,2]

该型号规格<Integer, Integer>comparingByValue需要for Java来推断类型Map.Entry.comparingByKey()


Nam*_*man 5

您正在寻找Comparator这样的自定义:

.sorted((o1, o2) -> o2.getValue().compareTo(o1.getValue()) == 0 ?
        o1.getKey().compareTo(o2.getKey()) : o2.getValue().compareTo(o1.getValue()))
Run Code Online (Sandbox Code Playgroud)

理论上,

  • 首先按降序比较值,o2.getValue().compareTo(o1.getValue())然后

  • 如果它们相等,则按升序比较键o1.getKey().compareTo(o2.getKey())