首先按值排序地图,然后按键排序



我实际上能够仅根据Map进行排序,我什至尝试像下面这样对它们进行排序:

我根据国家对学生进行排序,如果两个学生碰巧有相同的states则仅在匹配的国家中按StudentID排序。

到目前为止我尝试过:

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);

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

14=Orebro
26=Malmo
110=Orebro
146=Sweden
148=Sweden

预期输出:

  26=Malmo
  14=Orebro
  110=Orebro
  146=Sweden
  148=Sweden

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


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


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

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

输出:

6=Malmo
26=Malmo
14=Orebro
110=Orebro
146=Sweden
148=Sweden

前段时间我回答了如何在java中将名称与年龄一起排序,除了用于存储的数据结构之外,与您的问题有许多相似之处。遍历每个键并对其进行排序,然后在值中再次排序,然后对其进行排序是非常乏味的,并且会让您感到非常困惑。只要记住你以前如何使用 Map 时是如何遍历的 Map

for (Map.Entry<String,String> entry : somemap.entrySet()){..Some Statements..};

studentMaster.entrySet().stream()
    .sorted(Comparator.comparing((Map.Entry<Integer, String> m) -> m.getValue())
              .thenComparing(Map.Entry::getKey)).forEach(System.out::println);

输出

6=Malmo
26=Malmo
14=Orebro
110=Orebro
146=Sweden
148=Sweden
<</div> div class="one_answers">

Comparator应如下所示:

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);

输出:

6=Malmo
26=Malmo
14=Orebro
110=Orebro
146=Sweden
148=Sweden

2 种方式:

  • TreeSetComparable pojo一起使用。
  • TreeSet与自定义Comparator一起使用。

法典

啧.java

(将TreeSetComparable pojo一起使用。

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 = %sn", 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();
    }
}

Tmp比较器.java

(将TreeSet与自定义Comparator一起使用。

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 = %sn", 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()方法。

两者的输出是相同的:

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()需要改进,这是一个简化版本,仅用于测试。

最新更新