【问题标题】:How to handle nulls when using Java collection sort使用 Java 集合排序时如何处理空值
【发布时间】:2020-12-18 17:17:03
【问题描述】:

在 Java 中使用 Collection.sort 时,当内部对象之一为空时,我应该返回什么

例子:

Collections.sort(list, new Comparator<MyBean>() {
    public int compare(MyBean o1, MyBean o2) {
      return o2.getDate().compareTo(o1.getDate());
     } 

});

假设 o2 不为空,但 o2.getDate() 是,那么在添加空验证时我应该返回 1 还是 -1 或 0?

【问题讨论】:

    标签: java sorting collections nullpointerexception


    【解决方案1】:

    当然,这是您的选择。无论您编写什么逻辑,它都会定义排序规则。所以“应该”在这里并不合适。

    如果您希望 null 出现在任何其他元素之前,可以这样做

    public int compare(MyBean o1, MyBean o2) {
        if (o1.getDate() == null) {
            return (o2.getDate() == null) ? 0 : -1;
        }
        if (o2.getDate() == null) {
            return 1;
        }
        return o2.getDate().compareTo(o1.getDate());
    } 
    

    【讨论】:

    • 如果你想在前面升序它的空值但降序它们在最后怎么办。本质上完全翻转列表?
    • 我使用了这段代码并尝试了 Collections.reverseOrder() 并且与 Collections.reverse(List) 不一样;
    • @Jeremy 是的,你是对的,我面临同样的问题,所有空值数据排在第一位,有价值的数据排在最后。
    • @Jeremy 我得到了解决方案,只需交换 -1 和 1 的值。它工作正常,空值数据将出现在底部。
    【解决方案2】:

    在 Java 8 中你也可以使用nullsFirst():

    Comparator.nullsFirst(Date::compareTo).compare(dateOne, dateTwo);
    

    nullsLast():

    Comparator.nullsLast(Date::compareTo).compare(dateOne, dateTwo);
    

    这些方法会将null 排序到开头或结尾。无论您认为null 比其他对象大还是小,都没有错或对。正如其他人已经说过的那样,这完全取决于您。

    【讨论】:

      【解决方案3】:

      取决于对象是否为null,或者对象的内容是否为null。

      对象为空:

          import static java.util.Comparator.*;
      
          List<Data> listOfData = Arrays.asList(
                 new Data("foo"),
                 null,
                 new Data("bar"),
                 new Data("nyu"));
      
          listOfData.sort(nullsFirst(comparing(Data::getValue)));
          listOfData.forEach(System.out::println);
          //OUTPUT:
          // null
          // Data(bar)
          // Data(foo)
          // Data(nyu)
      

      对象的内容为空:

          List<Data> listOfData = Arrays.asList(
                 new Data("foo"),
                 new Data(null),
                 new Data("bar"),
                 new Data("nyu"));
      
      
          listOfData.sort(nullsFirst(
               comparing(Data::getValue, nullsFirst(naturalOrder()))));
      
          listOfData.forEach(System.out::println);
          //OUTPUT:
          // Data(null)
          // Data(bar)
          // Data(foo)
          // Data(nyu)
      

      【讨论】:

        【解决方案4】:

        这取决于,你认为 null 是大值还是小值。

        大多数时候你可以考虑 null

        这里 0 将是一个糟糕的返回值。

        【讨论】:

          【解决方案5】:

          根据 Nikita Rybak 的回答,我已经有了一个枚举比较器,并且只从这里添加空逻辑。

          public enum Orden implements Comparator<CmunParametrosDTO> {
                  ByStrDescripcion {
                      public int compare(CmunParametrosDTO item1, CmunParametrosDTO item2) {
                          if (item1.getStrDescripcion() == null && item2.getStrDescripcion() == null)
                              return 0;
                          if (item1.getStrDescripcion() == null)
                              return 1;
                          else if (item2.getStrDescripcion() == null)
                              return -1;
                          return item1.getStrDescripcion().compareTo(item2.getStrDescripcion());
                      }
                  }
                  public abstract int compare(CmunParametrosDTO item1, CmunParametrosDTO item2);
          
                  public Comparator<CmunParametrosDTO> ascending() {
                      return this;
                  }
          
                  public Comparator<CmunParametrosDTO> descending() {
                      return Collections.reverseOrder(this);
                  }
          }
          

          在这种形式中,我可以调用列表中的排序方法。

              if(isBolOrdAscendente()) Collections.sort(listado, CmunParametrosDTO.Orden.ByStrDescripcion .ascending());
              else Collections.sort(listado, CmunParametrosDTO.Orden.ByStrDescripcion .descending());
          

          【讨论】:

            【解决方案6】:

            如果比较两个属性,attr1 自然顺序,attr2 逆序,和 attr2 可以为空:

            datas.sort(comparing(Data::getAttr1, naturalOrder()).
                    thenComparing(Data::getAttr2, nullsLast(reverseOrder())));
            

            【讨论】:

              猜你喜欢
              • 2019-10-16
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-01-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多