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

时间:2019-02-01 16:07:04

标签: java java-stream

我实际上能够仅根据对我的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

4 个答案:

答案 0 :(得分:3)

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


代码不起作用的原因是,您两次调用Stream#sorted并使用两个单独的Comparator,因此在您的情况下,第一次调用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

答案 1 :(得分:1)

有时我会回答How to sort the name along with age in java,除了用于存储的数据结构外,还与您的问题有很多相似之处。 要遍历每个键并对其进行排序,然后再对值进行排序,然后再对它进行排序,这将非常繁琐,并且会使您感到非常困惑。只需记住当您不习惯使用 Stream 时是如何遍历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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

2种方式:

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

代码

Tmp.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 = %s\n", 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一起使用。)

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