关于java:按值排序按值排序,然后按键排序

Sorting a Map on First by value then by Key

本问题已经有最佳答案,请猛点这里访问。

实际上,我可以只根据键和值对我的Map进行排序,甚至尝试如下排序:

我根据国家对学生进行分类,如果两个学生恰好有相同的states,那么只在匹配的国家中按StudentID进行分类。

到目前为止我所做的尝试:

1
2
3
4
5
6
7
8
9
10
11
12
13
final Map<Integer, String> studentMaster = new HashMap<>() {{
        put(146,"Sweden");
        put(148,"Sweden");
        put(110,"Orebro");
        put(6,"Malmo");
        put(14,"Orebro");
        put(26,"Malmo");
    }  
    };
    studentMaster.entrySet().stream()
    .sorted((i1,i2)->i1.getValue().compareTo(i2.getValue()))
    .sorted((j1,j2)->j1.getKey().compareTo(j2.getKey()))
    .forEach(System.out::println);

我得到的结果**(实际输出)**

1
2
3
4
5
14=Orebro
26=Malmo
110=Orebro
146=Sweden
148=Sweden

预期输出:

1
2
3
4
5
  26=Malmo
  14=Orebro
  110=Orebro
  146=Sweden
  148=Sweden


注意:您的预期和实际输出与您添加到Map中的键不匹配。

你的代码不起作用的原因是你用两个单独的Comparator来调用Stream#sorted两次,所以第一次调用Stream#sorted在你的情况下是无用的(因为它被第二次调用覆盖了)。

我通过将自定义的Comparator传递给Stream#sorted,实现了您的预期输出:

1
2
Map.Entry.<Integer, String>comparingByValue()
    .thenComparing(Map.Entry.comparingByKey())

输出:

1
2
3
4
5
6
6=Malmo
26=Malmo
14=Orebro
110=Orebro
146=Sweden
148=Sweden


有时候,我回答了如何在Java中对名称进行分类,除了用于存储的数据结构之外,还有很多与您的问题相似的地方。遍历每一个键,然后对其进行值排序,然后再对其进行排序,这是非常繁琐的,而且会让您非常困惑。请记住,当您不使用流时,您如何在地图中遍历:

1
for (Map.Entry<String,String> entry : somemap.entrySet()){..Some Statements..};
1
2
3
studentMaster.entrySet().stream()
    .sorted(Comparator.comparing((Map.Entry<Integer, String> m) -> m.getValue())
              .thenComparing(Map.Entry::getKey)).forEach(System.out::println);

Output

1
2
3
4
5
6
6=Malmo
26=Malmo
14=Orebro
110=Orebro
146=Sweden
148=Sweden


2种方式:

  • 使用TreeSetComparablepojo。
  • 使用TreeSet和定制的Comparator

代码

tmp.java语言

(使用TreeSetComparablepojo。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import java.util.*;

public class Tmp {
    static class StudentMaster implements Comparable<StudentMaster> {
        private Integer id;
        private String master;

        public StudentMaster(Integer id, String master) {
            this.id = id;
            this.master = master;
        }

        @Override
        public int compareTo(StudentMaster other) {
            int masterFlag = master.compareTo(other.master);
            return (masterFlag == 0) ? id.compareTo(other.id) : masterFlag;
        }

        @Override
        public boolean equals(Object o) {
            StudentMaster osm = (StudentMaster) o;
            return id == osm.id && master.equals(osm.master);
        }

        @Override
        public int hashCode() {
            return Objects.hash(id, master);
        }

        public String toString() {
            StringBuilder sb = new StringBuilder();
            Formatter fm = new Formatter(sb);

            fm.format("id = %d, master = %s
"
, id, master);

            fm.close();
            return sb.toString();
        }
    }

    public static void test() {
        final Set<StudentMaster> smSet = new TreeSet<>();

        smSet.add(new StudentMaster(146,"Sweden"));
        smSet.add(new StudentMaster(148,"Sweden"));
        smSet.add(new StudentMaster(110,"Orebro"));
        smSet.add(new StudentMaster(6,"Malmo"));
        smSet.add(new StudentMaster(14,"Orebro"));
        smSet.add(new StudentMaster(26,"Malmo"));

        for (StudentMaster sm : smSet) {
            System.out.print(sm);
        }
    }

    public static void main(String[] args) {
        test();
    }
}

tmpcomparator.java

(使用TreeSet和自定义Comparator)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import java.util.*;

public class TmpComparator {
    static Comparator<StudentMaster> smc = new Comparator() {
        @Override
        public int compare(Object o1, Object o2) {
            StudentMaster sm1 = (StudentMaster) o1, sm2 = (StudentMaster) o2;

            int masterFlag = sm1.master.compareTo(sm2.master);
            return (masterFlag == 0) ? sm1.id.compareTo(sm2.id) : masterFlag;
        }
    };

    static class StudentMaster {
        private Integer id;
        private String master;

        public StudentMaster(Integer id, String master) {
            this.id = id;
            this.master = master;
        }

        @Override
        public boolean equals(Object o) {
            StudentMaster osm = (StudentMaster) o;
            return id == osm.id && master.equals(osm.master);
        }

        @Override
        public int hashCode() {
            return Objects.hash(id, master);
        }

        public String toString() {
            StringBuilder sb = new StringBuilder();
            Formatter fm = new Formatter(sb);

            fm.format("id = %d, master = %s
"
, id, master);

            fm.close();
            return sb.toString();
        }
    }

    public static void test() {
        final Set<StudentMaster> smSet = new TreeSet<>(smc);

        smSet.add(new StudentMaster(146,"Sweden"));
        smSet.add(new StudentMaster(148,"Sweden"));
        smSet.add(new StudentMaster(110,"Orebro"));
        smSet.add(new StudentMaster(6,"Malmo"));
        smSet.add(new StudentMaster(14,"Orebro"));
        smSet.add(new StudentMaster(26,"Malmo"));

        for (StudentMaster sm : smSet) {
            System.out.print(sm);
        }
    }

    public static void main(String[] args) {
        test();
    }
}

只需运行main()方法。

两者的输出相同:

1
2
3
4
5
6
id = 6, master = Malmo
id = 26, master = Malmo
id = 14, master = Orebro
id = 110, master = Orebro
id = 146, master = Sweden
id = 148, master = Sweden

提示

  • 在生产代码中,equals()需要改进,这是一个简化版本,仅用于测试。

Comparator应该如下所示:

1
2
3
4
5
6
7
8
Comparator<Entry<Integer, String>> comparator = (o1, o2) -> {
    int i = o1.getValue().compareTo(o2.getValue());
    if (i == 0) {
        return o1.getKey().compareTo(o2.getKey());
    } else {
        return i;
    }
};

然后传给Stream#sorted方法:studentMaster.entrySet().stream().sorted(comparator).forEach(System.out::println);

输出:

1
2
3
4
5
6
6=Malmo
26=Malmo
14=Orebro
110=Orebro
146=Sweden
148=Sweden