Stream的排序和sort()与sorted()的区别,nullsLast()与nullsFirst(),List<Map<String, Object>>的排序,对多个字段进行排序


在学习中很少使用Stream,但在工作中,我多次使用Stream进行排序,上一篇 Java Stream的简单应用中,连入门都算不上,现在,总算是能使用Stream进行一些比较常规特殊的排序了,之所以使用Stream当然是因为方便强大优雅,所以学起来

流排序

List<Map<String, Object>> maps,传入的不是对象集合,而是Map集合,(现在才意识到对象和Map很像,String类型的key,Object的value,就像对象,属性(字段)名为key,如Integer age; key为String类型的age(只是变量名),值为Integer类型(Object类型子类),key-value就是对象的属性名和属性值)
List.sort()方法和Stream.stream().sorted()的区别
我觉得两者在使用上没有大的区别,观其源码,参数是一样的,所以应该在使用上无感知(确实,我一直以为使用的sort()方法是sorted(),导致代码出了个很严重的bug),两者的差异,sort()是对集合本身做操作,会改变集合本身的结构(还是原集合,元素顺序(单只做排序元素本身和排序前是一样的,即元素未发生改变))发生改变,而sorted()不一样,如果不做collect(Collectors.toList())是不会改变原集合的结构的,如下图
注: 强转类型为(Double)是因为值可能为null,null无法转化为基本数据类型,必然抛异常

public static void main(String[] args) {
        List<Map<String, Object>> maps = new ArrayList<>();
        Map<String, Object> map1 = new HashMap<>();
        map1.put("score", 17.0);
        map1.put("dealerDistance", 3.0);
        Map<String, Object> map2 = new HashMap<>();
        map2.put("score", 18.0);
        map2.put("dealerDistance", 3.67);
        Map<String, Object> map3 = new HashMap<>();
        map3.put("score", null);
        maps.add(map1);
        maps.add(map2);
        maps.add(map3);
        //排序写法
        //Comparator.nullsLast(Comparator.reverseOrder())把null排序最后面,然后是Comparator.reverseOrder(),null值不参与逆序,null还是在最后
        List<Map<String, Object>> collect = maps.stream()
                //当删去第10行代码时map3中无名称为score的key,会出异常,用下面的注释代码可避免程序异常
                //(Map<String, Object> o) -> (o.get("score") == null ? -9999 : (Double) o.get("score")))
                .sorted(Comparator.comparing((Map<String, Object> o) -> (Double) o.get("score"),
                        Comparator.nullsLast(Comparator.reverseOrder()))
                        .thenComparing((Map<String, Object> o) -> ((double) o.get("dealerDistance")),
                                Comparator.nullsLast(Comparator.naturalOrder())))
                .collect(Collectors.toList());
        // ------------------------------------------------------------------------------
        //当list集合中map元素o中没有这个字段(score)时,吾观其源码,无score key返回null,给其排序数字为-9999),会出异常
        //注意这是List类的sort方法,不是Stream类的sorted方法,两者使用上好像没啥不同
        //Comparator.nullsLast(Double ::compareTo).reversed() 先是把null排最后面,再整体reversed(),包括为null的,所以null在最前面
        maps.sort(Comparator.comparing((Map<String, Object> o) -> ((Double) o.get("score")), Comparator.nullsLast(Double::compareTo).reversed())
                .thenComparingDouble((Map<String, Object> o) -> (o.get("dealerDistance") == null ? -9999 : (Double) o.get("dealerDistance"))));
        System.out.println(maps);
    }


集合元素初始顺序
在这里插入图片描述
Stream.sorted()并不操作原集合(maps)
在这里插入图片描述
List.sort()后,操作原集合(maps),元素顺序已发生改变

Comparator.nullsLast()和nullsFirst()的使用(两者类似)

以nullsLast()为例(项目逻辑中dealerDistance为null时排最后,以score排序时,score为null时也一样),具体详细看上面代码

Comparator.nullsLast(Comparator.reverseOrder())把null排序最后面,然后是Comparator.reverseOrder(),null值不参与逆序,null还是在最后
Comparator.nullsLast(Double ::compareTo).reversed() 先是把null排最后面,再整体reversed(),包括为null的,所以null在最前面
注:reverseOrder()是逆转排序即逆序,而reversed()是逆转仔细理解,这两个在意思上还是有区别的

sort() and sorted()源码

//List
default void sort(Comparator<? super E> c) {
    Object[] a = this.toArray();
        Arrays.sort(a, (Comparator) c);
        ListIterator<E> i = this.listIterator();
        for (Object e : a) {
            i.next();
            i.set((E) e);
        }
}

//Stream
Stream<T> sorted(Comparator<? super T> comparator);

各种尝试

以下是为了完成需求而做的各种尝试,以下代码不保证能跑通,也不保证正确,请根据自身业务需求多次调试

/**
 * 按分数降序(逆序)排序,分数高的排前,空的排最后,
 * 同分以距离(顺序)排序,距离小的排前
 * @param maps
 * @return
 */
private List<Map<String, Object>> sortByScore(List<Map<String, Object>> maps) {
    if (CollectionUtil.isEmpty(maps)) {
        return Collections.emptyList();
    }
    //上面说过Map和对象很像,但建议传递对象,做各种操作都会更加方便,如果是对象,就不需要下面各种探索了
    /*List<Map<String, Object>> collect = maps.stream()
            .sorted(Comparator.comparing(InfoVO :: getScore , Comparator.nullsLast(Comparator.reverseOrder()))
                    .thenComparing(InfoVO :: getDistanceDouble , Comparator.nullsLast(Comparator.naturalOrder())))
            .collect(Collectors.toList());
    return collect;*/
    ------------------------------------------------------------------------------
    /*List<Map> collect =
            maps.stream().sorted((o1, o2) -> Comparator.reverseOrder().compare((String)o1.get("score"), o2.get("score")))
                    .collect(Collectors.toList());*/
    //Collections.sort(maps, Comparator.comparing(o -> (((Double) o.get("score")))));
    //maps.sort(Comparator.comparing(o -> (Double) o.get("score")).reversed());
    //maps.sort(Comparator.comparingDouble(o -> (double) o.get("score")));

    //List<Map<String, Object>> collect4 = maps.stream().sorted(Comparator.comparing(o -> (Double) o.get("score")).reversed()).collect(Collectors.toList());
    ------------------------------------------------------------------------------
    /*Collections.sort(maps, (o1, o2) -> {
        Double score1 = (Double) o1.get("score");
        Double score2 = (Double) o2.get("score");
        int c = score1.compareTo(score2);
        if (c != 0) {
            return c;
        }
        Double dealerDistance1 = (Double) o1.get("dealerDistance");
        Double dealerDistance2 = (Double) o2.get("dealerDistance");
        return dealerDistance1.compareTo(dealerDistance2);
    });*/
    ------------------------------------------------------------------------------
    maps.sort((o1, o2) -> {
        Double score1 = (Double) o1.get("score");
        Double score2 = (Double) o2.get("score");
        //逆序
        int c = score2.compareTo(score1);
        if (c != 0) {
            return c;
        }
        Double dealerDistance1 = (Double) o1.get("dealerDistance");
        Double dealerDistance2 = (Double) o2.get("dealerDistance");
        //顺序
        return dealerDistance1.compareTo(dealerDistance2);
    });
    return maps;
}
------------------------------------------------------------------------------
//排序写法
maps.stream().sorted(Comparator.comparing((Map<String, Object> o) -> ((double) o.get("score")),
                Comparator.nullsLast(Comparator.reverseOrder()))
                .thenComparing((Map<String, Object> o) -> ((double) o.get("dealerDistance")),
                        Comparator.nullsLast(Comparator.naturalOrder())));
------------------------------------------------------------------------------
//当list集合中map元素o中没有这个字段(score)时,吾观其源码,无score key返回null,给其排序数字为-9999),会出异常
//注意这是List类的sort方法,不是Stream类的sorted方法,两者使用上好像没啥不同
maps.sort(Comparator.comparing((Map<String, Object> o) -> (o.get("score") == null ? -9999 : (Double) o.get("score"))).reversed()
                    .thenComparingDouble((Map<String, Object> o) -> (o.get("dealerDistance") == null ? -9999 : (Double) o.get("dealerDistance"))));
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值