【问题标题】:Sorting a Map on First by value then by Key [duplicate]首先按值对地图进行排序,然后按键[重复]
【发布时间】:2019-06-26 05:49:47
【问题描述】:

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

【问题讨论】:

  • 如果不需要存储排序的条目,那么自定义比较器应该就足够了
  • @CaseyRule 我不相信这是重复的,因为 OP 想要按值排序 然后 按键。
  • @JacobG。我实际上已将stackoverflow.com/questions/3074154/… 确定为与此问题重复,但该问题被标记为与stackoverflow.com/questions/109383/… 重复。在这种情况下,重复的传递性似乎不成立:)
  • @CaseyRule 啊,这很有趣;好收获!
  • 你的问题解决了吗??

标签: java java-stream


【解决方案1】:

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


您的代码不起作用的原因是因为您使用两个单独的Comparators 调用了两次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

【讨论】:

    【解决方案2】:

    有时我回答了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
    

    【讨论】:

      【解决方案3】:

      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
      

      【讨论】:

        【解决方案4】:

        两种方式:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-11-03
          • 2018-05-30
          • 2014-01-18
          • 2023-04-06
          • 1970-01-01
          • 2020-09-14
          • 2023-03-04
          • 2011-02-17
          相关资源
          最近更新 更多