【问题标题】:Custom sorting by two parameters not working correctly按两个参数自定义排序无法正常工作
【发布时间】:2021-05-09 05:19:29
【问题描述】:
public List<List<Integer>> demo(int[][] buildings) {
    List<List<Integer>> tracker = new ArrayList<>();
    int pointer = 0;
    for (int i = 0; i < buildings.length; i++) {
        tracker.add(Arrays.asList(buildings[i][0], -buildings[i][2]));
        tracker.add(Arrays.asList(buildings[i][1], buildings[i][2]));
    }
    Collections.sort(tracker, (a, b) -> {
        if (a.get(0) != b.get(0)) {
            return a.get(0).compareTo(b.get(0));
        } else {
            return a.get(1).compareTo(b.get(1));
        }
    });
    return tracker;
}

当我输入时:

[[1,10001,10000],[2,10001,9999],[3,10001,9998]]

我得到的输出是:

[[1,-10000],[2,-9999],[3,-9998],[10001,10000],[10001,9999],[10001,9998]]

这不是我期望的输出,因为我的排序规则应该是当10001 == 10001 时,第二个坐标较小的应该首先排列。

【问题讨论】:

    标签: java list sorting collections


    【解决方案1】:

    我认为问题在于整数缓存。对于低数字,整数被缓存,所以!= 有效。对于大数字,使用新的Integers。使用 Integer.equals 检查是否相等。

    变化:

    if(a.get(0) != b.get(0))
    

    进入:

    if( a.get(0).equals(b.get(0)) )
    

    否则,您是在比较参考而不是值。

    另一种方法是使用 Comparator 类的辅助方法。

    Comparator.<List<Integer>>comparing( list -> list.get(0) ).thenComparing(list-> list.get(1) );
    

    【讨论】:

      【解决方案2】:

      在 Java 中比较对象时,总是使用 equals 或 compareTo(相应地)。

      代替:

         if(a.get(0) != b.get(0)){ // <---- THIS IS WRONG
              return a.get(0).compareTo(b.get(0));
          }
      

      您可以重复使用 compareTo 的结果:

      a.get(0).compareTo(b.get(0));
      

      即:

          int result = a.get(0).compareTo(b.get(0));
          return result == 0 ? a.get(1).compareTo(b.get(1)) : result;
      

      此外,您可以简单地使用 tracker.sort 并将比较逻辑替换为 Comparator 链,而不是 Collection.sort

      tracker.sort(Comparator.comparingInt((List<Integer> a) -> a.get(0))
                             .thenComparingInt(a -> a.get(1)));
      

      一个运行的例子:

      public class A {
      
          public static List<List<Integer>> demo(int[][] buildings) {
              List<List<Integer>> tracker = new ArrayList<>();
              int pointer = 0;
              for (int[] building : buildings) {
                  tracker.add(Arrays.asList(building[0], -building[2]));
                  tracker.add(Arrays.asList(building[1], building[2]));
              }
              tracker.sort(Comparator.comparingInt((List<Integer> a) -> a.get(0))
                     .thenComparingInt(a -> a.get(1)));
              return tracker;
          }
      
      
          public static void main(String[] args) {
              int[][] x = new int[][]{{1,10001,10000},{2,10001,9999},{3,10001,9998}};
              List<List<Integer>> demo = demo(x);
              demo.forEach(System.out::println);
          }
      }
      

      输出:

      [1, -10000]
      [2, -9999]
      [3, -9998]
      [10001, 9998]
      [10001, 9999]
      [10001, 10000]
      

      【讨论】:

        【解决方案3】:

        Answer by matt 是正确的。

        这是修复它的另一种方法。不要两次比较值,即不要同时使用equals() compareTo():

        Collections.sort(tracker, (a, b) -> {
            int cmp = a.get(0).compareTo(b.get(0));
            if (cmp == 0) {
                cmp = a.get(1).compareTo(b.get(1));
            }
            return cmp;
        } );
        

        更简单的解决方案:

        Collections.sort(tracker, Comparator.comparing(x -> x.get(0))
                                        .thenComparing(x -> x.get(1)));
        

        根据编译器的版本,可能需要“提示”才能知道x 是什么。两者都应该做到这一点,没有一个比另一个更好。

        Collections.sort(tracker, Comparator.<List<Integer>>comparing(x -> x.get(0))
                                                       .thenComparing(x -> x.get(1)));
        
        Collections.sort(tracker, Comparator.comparing((List<Integer> x) -> x.get(0))
                                        .thenComparing(x -> x.get(1)));
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-12-02
          • 1970-01-01
          • 2016-07-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多