按值排序Map,然后按键排序

4

我实际上可以根据 对我的 Map 进行排序,我甚至尝试按以下方式进行排序:

我根据国家对学生进行排序,如果两个学生恰好拥有相同的 ,则仅在匹配的国家中按 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

如果不需要存储已排序的条目,则自定义比较器就足够了。 - HamoriZ
@CaseyRule 我不认为这是重复的,因为原帖想要按值然后按键排序。 - Jacob G.
@JacobG。我实际上已经确定了https://dev59.com/1XA75IYBdhLWcg3w182G与此问题重复,但是该问题被标记为https://dev59.com/qXVD5IYBdhLWcg3wDG_m的重复。看起来在这种情况下,重复的传递属性并没有保持 :) - Casey Rule
@CaseyRule 哦,这很有趣;发现得好! - Jacob G.
你的问题解决了吗? - Vishwa Ratna
您首先需要按照值的基础进行排序,然后如果值相同,则按照键进行排序。 - Arpit
4个回答

3
注意:您期望的输出和实际输出与您添加到Map中的键不匹配。
您的代码无法正常工作的原因是您两次调用了带有两个不同ComparatorStream#sorted,因此在您的情况下第一次调用Stream#sorted是无用的(因为它被第二次调用覆盖)。
通过向Stream#sorted传递自定义Comparator,我能够实现您期望的输出。
Map.Entry.<Integer, String>comparingByValue()
    .thenComparing(Map.Entry.comparingByKey())

输出:

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

2
不久前,我回答了一个关于如何在Java中按名称和年龄排序的问题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);

Output

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

1
“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

0

有两种方法:

  • 使用带有Comparable POJO的TreeSet
  • 使用自定义ComparatorTreeSet

代码

Tmp.java

(使用具有Comparable POJO的TreeSet。)

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

(使用自定义的ComparatorTreeSet

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接