stream流中sorted排序浅析

        项目中经常用到stream流的sorted排序,用的时候老感觉迷迷糊糊的,于是今天看了看顺便记录一下,以后再来复习。

        stream中有两个sorted方法:

        (1)一个无参的方法

                Stream<T> sorted();

                查看它的实现类,往里进,发现它默认使用的是自然排序compareTo

 

        (2)一个有参的方法

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

                该方法需要传一个比较器参数

                1)你可以通过实现 java.util.Comparator定制一个比较器

list.stream().sorted((o1, o2) -> {
    if((o1.getAge() - o2.getAge()) < 0){
        return -1
    }else if ((o1.getAge() - o2.getAge()) > 0){
        return 1
    }else {
        return 0;
    }
}

                        上面的也可以写成下面这样,定制排序里使用自然排序

list.stream().sorted((o1, o2) -> o1.getAge().compareTo(o2.getAge()));

                2)处理实现util包下的Comparator,还可以使用stream中封装的Comparator接口

                        stream下的Comparator有多个方法用来自定义排序规则来生成一个比较器给sorted方法。经常用的有comparing和thenComparing来配合使用,当comparing中的条件相同时按thenComparing中的条件进行排序,其他的比如comparingInt、comparingLong、comparingDouble等方法会将你的条件转成对应的类型,通过包装类下的compare进行排序

public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
    }



public static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2));
    }


public static<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));
    }

                在这里着重记录一下comparing方法,它有两个重载方法

                1、有一个入参的方法

public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor)
    {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
    }

                入参keyExtractor是一个获取比较条件的表达式,例如对List<User>按User中的age排序,可以这样写

list.stream().sorted(Comparator.comparing(User::getAge));
//或者
list.stream().sorted(Comparator.comparing(e -> e.getAge()));

//项目中有的数据不是用实体类接收的,而是用map接收的数据库数据,可以这样写

List<Map<String, Object>> listMap = server.getAllUserInfo();
listMap.stream.sorted(Comparator.comparing(
    e -> Integer.parseInt(String.valueOf(e.get("age")))
))
        Objects.requireNonNull(keyExtractor);是对入参的一个判空,为空就抛出
throw new NullPointerException();异常
public static <T> T requireNonNull(T obj) {
        if (obj == null)
            throw new NullPointerException();
        return obj;
    }

                return (Comparator<T> & Serializable)
            (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));

                个人对这段代码的理解是,传入集合中用于比较的两个参数c1,c2,keyExtractor.apply(c1)会将c1根据传入的表达式进行获取比较字段,例如:c1 是一个User对象,

执行代码keyExtractor.apply(c1) 后会返回一个age年龄数据,两个年龄数据会通过compareTo方法进行自然排序

        2、有两个入参的方法

public static <T, U> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor,
            Comparator<? super U> keyComparator)
    {
        Objects.requireNonNull(keyExtractor);
        Objects.requireNonNull(keyComparator);
        return (Comparator<T> & Serializable)
            (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
                                              keyExtractor.apply(c2));
    }

        和一个入参的方法一样,keyExtractor是获取用于比较字段的表达式;

        一个入参的方法底层使用的是compareTo的自然比较器,该两个入参的方法里第二个参数是传入一个自定义的比较器,例如:

//一个简单的例子
List<User> list = server.getAllUserInfo2();

list.stream().sorted(Comparator.comparing(e -> e, (o1, o2) -> {
            if((o1.getAge() - o2.getAge()) < 0){
                return -1;
            }else if((o1.getAge() - o2.getAge()) > 0){
                return 1;
            }else{
                return 0;
            }
        }));
//用多个属性排序,和使用thenComparing方法相同
list.stream().sorted(Comparator.comparing(e -> e, (o1, o2) -> {
            if((o1.getAge() - o2.getAge()) < 0){
                return -1;
            }else if((o1.getAge() - o2.getAge()) > 0){
                return 1;
            }else{
                //年龄相等时,用另一个属性排序
                if((o1.getUserName().hashCode() - o2.getUserName().hashCode()) < 0){
                    return -1;
                }else if((o1.getUserName().hashCode() - o2.getUserName().hashCode()) > 0){
                    return 1;
                }else {
                    return 0;
                }
            }
        }));

最后说一下comparator接口中的reversed()方法

default Comparator<T> reversed() {
        return Collections.reverseOrder(this);
    }

//进入reverseOrder

public static <T> Comparator<T> reverseOrder(Comparator<T> cmp) {
        if (cmp == null)
            return reverseOrder();

        if (cmp instanceof ReverseComparator2)
            return ((ReverseComparator2<T>)cmp).cmp;

        return new ReverseComparator2<>(cmp);
    }

//进入reverseOrder

public static <T> Comparator<T> reverseOrder() {
        return (Comparator<T>) ReverseComparator.REVERSE_ORDER;
    }

//查看ReverseComparator.REVERSE_ORDER

private static class ReverseComparator
        implements Comparator<Comparable<Object>>, Serializable {

        private static final long serialVersionUID = 7207038068494060240L;

        static final ReverseComparator REVERSE_ORDER
            = new ReverseComparator();

        public int compare(Comparable<Object> c1, Comparable<Object> c2) {
            return c2.compareTo(c1);
        }

        private Object readResolve() { return Collections.reverseOrder(); }

        @Override
        public Comparator<Comparable<Object>> reversed() {
            return Comparator.naturalOrder();
        }
    }

//可以看到一个compare方法里使用了c2.compareTo(c1)来进行实现倒叙,c1.compareTo(c2)是正序

        好了,对于sorted的浅显分析到此为止,有错误的地方请各位大佬指出,谢谢。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值