JDK8新特性详细笔记

JDK8新特性

1、Lambda表达式&函数式接口

1.1、什么是Lambda表达式?

lambda表达式可以理解为一种匿名函数的代替,lambda允许将函数作为一个方法的参数(函数作为方法方式传递),将代码像数据一样传递,目的是简化代码的编写。

1.2、什么是函数式接口?

lambda表达式需要函数式接口的支持

所谓函数式接口,是指只有一个抽象方法

另外JDK8也提供了一个注解,帮助我们编程时检查语法是否符合

@FunctionalInterface

1.3、Lambda表达式使用案例

lambda表达式的基本语法:

函数式接口 变量名 = (参数1,参数2...)->{
	//方法体
};

案例1:

public static void main(String[] args) {
        //匿名函数
        Runnable runnable1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("run...");
            }
        };
        new Thread(runnable1).start();
        //lambda表达式第二种写法
        Runnable runnable2 = ()->{System.out.println("aaa......");};
        new Thread(runnable2).start();
        //lambda表达式第三种写法
        new Thread(()->{System.out.println("bbb......");}).start();
        //第四种写法,如果方法体里面只有一条语句的时候,可以省去大括号
        new Thread(()-> System.out.println("ccc......")).start();
    }

案例2:

public static void main(String[] args) {
        //匿名函数
        Comparator<String> comparator = new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.length()-o2.length();
            }
        };
        TreeSet<String> treeSet = new TreeSet<>(comparator);

        //lambda表达式
        Comparator<String> comparator1 = (o1,o2)->o1.length()-o2.length();
        TreeSet<String> treeSet1 = new TreeSet<>(comparator1);

        //lambda表达式
        TreeSet<String> treeSet2 = new TreeSet<>((o1,o2)->o1.length()-o2.length());
    }

1.4、Lambda表达式注意事项

Lambda引入了新的操作符:->(箭头操作符),->将表达式分成两部分

左侧:(参数1,参数2…)表示参数列表;

右侧:{}内部是方法体;

1、形参列表的数据类型自动推断;

2、如果形参列表为空,只需保留();

3、如果形参只有1个,()可以省略,只需要参数的名称即可;

4、如果执行语句只有1句,且无返回值,{}可以省略,若有返回值,则若想省去{},则必须同事省略return,且执行语句也保证只有1句;

5、lambda不会生成一个单独的内部类文件;

6、lambda表达式若访问了局部变量,则局部变量必须是final的,若是局部变量没有加final关键字,系统会自动添加,此后在修改该局部变量,会报错;

2、流式编程-StreamAPI

2.1、什么是Stream?

Stream是Java8中处理数组,集合的抽象概念,它可以指定你希望对集合进行操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API对集合数据进行操作,就类似于使用SQL执行的数据库查询。

一个Stream表面上与一个集合很类似,集合中保存的是数据,而流设置的是对数据的操作。

Steam的特点:

1、Stream 自己不会存储元素。

2、Stream 不会改变源对象,相反,它们会返回一个持有结果的新Stream。

3、Stream 操作是延迟执行的,这意味看它们等到需要结果的时候才执行。

Stream遵循“做什么,而不是怎么做”的原则。只需要描述要做什么,而不用考虑程序是怎么实现的。

2.2、快速体验StreamAPI的特点

List<String> list = new ArrayList<>();
list.add("a");
list.add("hello");
list.add("stream");

//传统写法
int count = 0;
for (String s : list) {
    if (s.length()>3){
        count++;
    }
}
System.out.println(count);

//StreamAPI结合lambda表达式
//1、链式编程
//2、函数式接口
//3、lambda表达式
long count1 = list.stream().filter((s) -> s.length() > 3).count();
System.out.println(count1);

2.3、使用StreamAPI的步骤

1、创建一个Stream (创建)

2、在一个或多个步骤中,将初始Stream转化到另一个Stream的中间操作。(中间操作)

3、使用一个终止操作来产生一个结果,该操作会强制它之前的延迟操作立即执行,在这之后,该Stream就不会再被使用了。(终止操作)

2.4、创建Stream的方式

上面已经演示了集合创建Stream的方式

这里面在补充一个重数组的方式

int[] array = new int[]{1,2,3};
IntStream arrayStream = Arrays.stream(array);
long count2 = arrayStream.filter(i -> i > 2).count();
System.out.println(count2);

2.5、Stream的中间操作

实体类:

package com.com.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {

    private String name;
    private int age;
    private int salary;

}

2.5.1、筛选和切片(filter,limit,skip(n),distinct)

public static void main(String[] args) {
        List<Employee> list = new ArrayList<>();
        list.add(new Employee("zhangsan",20,1000));
        list.add(new Employee("lisi",30,2000));
        list.add(new Employee("wangwu",40,3000));
        list.add(new Employee("wangwu",40,3000));

        System.out.println("$$$$$$$$$筛选$$$$$$$$$");

        //筛选
        Stream<Employee> employeeStream = list.stream().filter(e -> e.getAge() > 30);
        employeeStream.forEach(e-> System.out.println(e.getName()));

        System.out.println("$$$$$$$$$获取第一个$$$$$$$$$");

        //获取第一个
        Stream<Employee> limit = list.stream().limit(1);
        limit.forEach(System.out::println);

        System.out.println("$$$$$$$$$跳过一个$$$$$$$$$");

        //跳过一个
        Stream<Employee> skip = list.stream().skip(1);
        skip.forEach(System.out::println);

        System.out.println("$$$$$$$$$去重$$$$$$$$$");

        //自动调用equals和hashcode
        Stream<Employee> distinct = list.stream().distinct();
        distinct.forEach(System.out::println);
    }

2.5.2、map(映射)

//map一接收Lambda,
//将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
Stream<String> stringStream = list.stream().map(e -> e.getName());
stringStream.forEach(System.out::println);

//小写转换大写
List<String> strings = Arrays.asList("a", "b", "c");
Stream<String> stringStream1 = strings.stream().map(String::toUpperCase);
stringStream1.forEach(System.out::println);

2.5.3、排序(sorted)

System.out.println("$$$$$$$$$第一种升序排序$$$$$$$$$");

Stream<Integer> sorted = list.stream().map(Employee::getAge).sorted();
sorted.forEach(System.out::println);

System.out.println("$$$$$$$$$第二种升序排序$$$$$$$$$");

List<Employee> collect = list.stream().sorted(Comparator.comparing(Employee::getAge)).collect(Collectors.toList());
collect.forEach(System.out::println);

System.out.println("$$$$$$$$$第二种降序排序$$$$$$$$$");

List<Employee> collect1 = list.stream().sorted(Comparator.comparing(Employee::getAge).reversed()).collect(Collectors.toList());
collect1.forEach(System.out::println);

System.out.println("$$$$$$$$$定制排序$$$$$$$$$");
Stream<Employee> sorted1 = list.stream().sorted((o1, o2) -> {
    if (o1.getAge() == o2.getAge()) {
        return o1.getName().compareTo(o2.getName());
    } else {
        return o1.getAge() - o2.getAge();
    }
});
sorted1.forEach(System.out::println);

2.6、终止操作

2.6.1、遍历

forEach

2.6.2、查找和匹配

allMatch #检查是否匹配所有元素
anyMatch #检查是否至少匹配一个元素
noneMatch #检查是否没有匹配的元素
findFirst #返回第一个值
findAny #返回任意一个值
count  #返回流中元素的总个数
max #返回流中最大的值
min #返回流中最小的值
System.out.println("$$$$$$$$$查询匹配$$$$$$$$$");

//检查是否匹配所有元素
boolean b1 = list.stream().allMatch(e -> e.getAge() > 30);
System.out.println(b1);

//检查是否至少匹配一个元素
boolean b2 = list.stream().anyMatch(e -> e.getAge() > 30);
System.out.println(b2);

//检查是否没有匹配的元素
boolean b3 = list.stream().noneMatch(e -> e.getName().equals("666"));
System.out.println(b3);

//返回第一个值
Optional<Employee> first = list.stream().findFirst();
if (first.isPresent()) {
Employee employee = first.get();
System.out.println(employee);
} else {
System.out.println("no value?");
}

//返回任意一个值
Optional<Employee> any = list.stream().filter(e->e.getAge()>30).findAny();
if (any.isPresent()) {
Employee employee = any.get();
System.out.println(employee);
} else {
System.out.println("no value?");
}

//返回流中元素的总个数
long count = list.stream().filter(e->e.getAge()>30).count();
System.out.println(count);

//返回流中最大的值
Optional<Employee> max = list.stream().max((x, y) -> x.getAge() - y.getAge());
System.out.println(max.get());

//返回流中最小的值
Optional<Employee> min = list.stream().min((x, y) -> x.getAge() - y.getAge());
System.out.println(min.get());

2.7 Stream的串行和并行

Stream有串行和并行两种,串行Stream上的操作是在一个线程中依次完成,而并行Stream则是在多个线程上同时执行。

串行:

public static void main(String[] args) {
        //初始化数据
        int max = 1000000;
        List<String> arrayList = new ArrayList<>(max);
        for (int i = 0; i < max; i++) {
            UUID uuid = UUID.randomUUID();
            arrayList.add(uuid.toString());
        }
        //串行计算 耗时:558
        /*long start = System.currentTimeMillis();
        long count = arrayList.stream().sorted().count();
        System.out.println(count);
        long end = System.currentTimeMillis();
        long millis = end - start;
        System.out.println(millis);*/

        //并行计算 耗时:289
        long start = System.currentTimeMillis();
        long count = arrayList.parallelStream().sorted().count();
        System.out.println(count);
        long end = System.currentTimeMillis();
        long millis = end - start;
        System.out.println(millis);

    }

2.8 Collectors 使用

在Java Stream中,我们通常需要处理后的Stream转换成集合类,这个时候就需要用到stream.collect方法。collect方法需要传入一个Collector类型,要实现Collector还是很麻烦的,需要实现好几个接口。

于是Java提供了更简单的Collectors工具类方便我们使用构建Collector。

注意:Collectors不能再main方法执行,因为main方法是静态有冲突,使用单元测试即可。

下面具体讲解Collectors用法。

List<String> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();

List<Users> usersList1 = new ArrayList<>();
List<Users> usersList2 = new ArrayList<>();

@Before
public void load(){
    //初始数据集合 一个是里面元素无重复的集合,一个是里面元素有重复的集合
    list1 = Arrays.asList("jack", "bob", "alice", "mark");
    list2 = Arrays.asList("jack", "jack", "alice", "mark");
    
    //无重复
    usersList1.add(new Users(1,"张三",12));
    usersList1.add(new Users(2,"李四",30));
    usersList1.add(new Users(3,"王五",20));
    usersList1.add(new Users(4,"赵六",12));

    //重复
    usersList2.add(new Users(1,"张三",12));
    usersList2.add(new Users(2,"李四",30));
    usersList2.add(new Users(3,"王五",20));
    usersList2.add(new Users(4,"赵六",12));
    usersList2.add(new Users(4,"赵六",12));
}

实体:

package com.test.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Users {

    private int id;
    private String name;
    private int age;

}

2.8.1、toList() 转list集合

将Stream转换为list。这里转换的list是ArrayList,如果想要转换成特定的list,需要使用toCollection方法

//转换toList
@Test
public void toList(){
    List<String> collect1 = list1.stream().collect(Collectors.toList());
    collect1.forEach(System.out::println);

    System.out.println("---------------------------");

    List<Users> collect2 = usersList1.stream().collect(Collectors.toList());
    collect2.forEach(System.out::println);
}

2.8.2、toSet() 转Set集合

toSet将Strem转换成Set,这里转换的是HashSet。如果需要特别指定Set,那么需要使用toCollection()方法。

因为Set中是没有重复元素的,如果我们使用list2集合数据来转换的话,会发现最终结果中只有一个jack。

//转换toSet
@Test
public void toSet(){
		Set<String> collect1 = list1.stream().collect(Collectors.toSet());
        collect1.forEach(System.out::println);

        System.out.println("---------------------------");

        Set<String> collect2 = list2.stream().collect(Collectors.toSet());
        collect2.forEach(System.out::println);

        System.out.println("---------------------------");

        Set<Users> collect3 = usersList1.stream().collect(Collectors.toSet());
        collect3.forEach(System.out::println);

        System.out.println("---------------------------");

        Set<Users> collect4 = usersList2.stream().collect(Collectors.toSet());
        collect4.forEach(System.out::println);
}

2.8.3、toMap() 转Map集合

toMap接收两个参数,第一个参数是keyMapper,第二个参数是valueMapper

//转换toMap
@Test
public void toMap(){
		//无重复
        Map<String, String> collect1 = list1.stream().collect(Collectors.toMap(String::new, s -> s));
        collect1.forEach((key,value)->{
            System.out.println("key:" +key+" ---- value:"+value);
        });

        System.out.println("---------------------------");

        //重复
        //如果stream中有重复的值,则转换会报IllegalStateException异常
        //在toMap中添加第三个参数mergeFunction,来解决冲突的问题
        Map<String, String> collect2 = list2.stream().collect(Collectors.toMap(String::new, s -> s,(item,mergeItem)->item));
        collect2.forEach((key,value)->{
            System.out.println("key:" +key+" ---- value:"+value);
        });

        System.out.println("---------------------------");

        Map<Integer, String> collect3 = usersList1.stream().collect(Collectors.toMap(Users::getId, Users::getName));
        collect3.forEach((key,value)->{
            System.out.println("key:" +key+" ---- value:"+value);
        });

        System.out.println("---------------------------");

        Map<Integer, String> collect4 = usersList2.stream().collect(Collectors.toMap(Users::getId, Users::getName,		(item,mergeItem)->item));
        collect4.forEach((key,value)->{
            System.out.println("key:" +key+" ---- value:"+value);
        });
}

2.8.4、toCollection()转自定义集合

上面的toMap,toSet转换出来的都是特定的类型,如果我们需要自定义,则可以使用toCollection(),下面我们转换成了LinkedList

//转换toCollection
@Test
public void toCollection(){
    LinkedList<String> collect1 = list1.stream().collect(Collectors.toCollection(LinkedList::new));
    collect1.forEach(System.out::println);

    System.out.println("---------------------------");

    LinkedList<Users> collect2 = usersList1.stream().collect(Collectors.toCollection(LinkedList::new));
    collect2.forEach(System.out::println);
}

2.8.5、collectingAndThen()转换后再次操作

collectingAndThen允许我们对生成的集合再做一次操作,相当对Stream转换后再次操作

//collectingAndThen允许我们对生成的集合再做一次操作
@Test
public void collectingAndThen(){
		List<String> collect1 = list1.stream().collect(Collectors.collectingAndThen(Collectors.toList(), s -> {
            return new ArrayList(s);
        }));
        collect1.forEach(System.out::println);

        System.out.println("---------------------------");

        ArrayList collect2 = usersList1.stream().collect(Collectors.collectingAndThen(Collectors.toList(), u -> {
            //转换list后进行改变某个元素的属性值
            u.get(0).setAge(20);
            return new ArrayList(u);
        }));
        collect2.forEach(System.out::println);
}

2.8.6、joining() 元素连接

joining用来连接stream中的元素

//joining连接结合元素
@Test
public void joining(){
    //第一种连接方式
    String collect1 = list1.stream().collect(Collectors.joining());
    System.out.println("第一种连接方式:"+collect1);
    //第二种连接方式,使用空格进行连接,充当分隔符操作
    String collect2 = list1.stream().collect(Collectors.joining(" "));
    System.out.println("第二种连接方式:"+collect2);
    //第三种连接方式,追加前缀和后缀
    String collect3 = list1.stream().collect(Collectors.joining(" ","[","]"));
    System.out.println("第三种连接方式:"+collect3);
    
    System.out.println("---------------------------");

    String collect4 = usersList1.stream().map(Users::getName).collect(Collectors.joining());
    System.out.println(collect4);

    String collect5 = usersList1.stream().map(Users::getName).collect(Collectors.joining(","));
    System.out.println(collect5);

    String collect6 = usersList1.stream().map(Users::getName).collect(Collectors.joining(",","{","}"));
    System.out.println(collect6);
}

2.8.7、counting() 统计个数

counting主要用来统计stream中元素的个数

//统计stream中的元素的个数
@Test
public void counting(){
		Long collect1 = list1.stream().collect(Collectors.counting());
        System.out.println(collect1);

        System.out.println("---------------------------");

        Long collect2 = usersList1.stream().collect(Collectors.counting());
        System.out.println(collect2);
}

2.8.8、summarizing()生成统计类

summarizing/Double/Long/Int为stream中的元素生成了统计信息,返回的结果是一个统计类

//summarizingDouble/Long/Int为stream中的元素生成了统计信息,返回的结果是一个统计类
@Test
public void summarizing(){
		//summarizingInt 统计
        IntSummaryStatistics collect1 = list1.stream().collect(Collectors.summarizingInt(String::length));
        System.out.println(collect1);

        System.out.println("---------------------------");

        //summarizingDouble 统计
        DoubleSummaryStatistics collect2 = list1.stream().collect(Collectors.summarizingDouble(String::length));
        System.out.println(collect2);

        System.out.println("---------------------------");

        //summarizingLong 统计
        LongSummaryStatistics collect3 = list1.stream().collect(Collectors.summarizingLong(String::length));
        System.out.println(collect3);

        System.out.println("---------------------------");

        DoubleSummaryStatistics collect4 = usersList1.stream().collect(Collectors.summarizingDouble(Users::getAge));
        System.out.println(collect4);

        System.out.println("---------------------------");

        LongSummaryStatistics collect5 = usersList1.stream().collect(Collectors.summarizingLong(Users::getAge));
        System.out.println(collect5);

        System.out.println("---------------------------");

        IntSummaryStatistics collect6 = usersList1.stream().collect(Collectors.summarizingInt(Users::getAge));
        System.out.println(collect6);
}

2.8.9、averaging()求平均值

averaging/Double/Long/Int对stream中的元素做平均

//averaging/Double/Long/Int对stream中的元素做平均操作
@Test
public void averaging(){
        //averaging Double 平均
        Double collect1 = list1.stream().collect(Collectors.averagingDouble(String::length));
        System.out.println(collect1);

        System.out.println("---------------------------");

        //averaging Long 平均
        Double collect2 = list1.stream().collect(Collectors.averagingLong(String::length));
        System.out.println(collect2);

        System.out.println("---------------------------");

        //averaging Int 平均
        Double collect3 = list1.stream().collect(Collectors.averagingInt(String::length));
        System.out.println(collect3);

        System.out.println("---------------------------");

        Double collect4 = usersList1.stream().collect(Collectors.averagingDouble(Users::getAge));
        System.out.println(collect4);

        System.out.println("---------------------------");

        Double collect5 = usersList1.stream().collect(Collectors.averagingLong(Users::getAge));
        System.out.println(collect5);

        System.out.println("---------------------------");

        Double collect6 = usersList1.stream().collect(Collectors.averagingInt(Users::getAge));
        System.out.println(collect6);
}

2.8.10、summing()求和

summing/Double/Long/Int对stream中的元素做sum操作

//summing/Double/Long/Int对stream中的元素做sum操作
@Test
public void summing(){
		//summingDouble 求和
        Double collect1 = list1.stream().collect(Collectors.summingDouble(String::length));
        System.out.println(collect1);

        System.out.println("---------------------------");

        //summingLong 求和
        Long collect2 = list1.stream().collect(Collectors.summingLong(String::length));
        System.out.println(collect2);

        System.out.println("---------------------------");

        //summingInt 求和
        Integer collect3 = list1.stream().collect(Collectors.summingInt(String::length));
        System.out.println(collect3);

        System.out.println("---------------------------");

        Double collect4 = usersList1.stream().collect(Collectors.summingDouble(Users::getAge));
        System.out.println(collect4);

        Long collect5 = usersList1.stream().collect(Collectors.summingLong(Users::getAge));
        System.out.println(collect5);

        Integer collect6 = usersList1.stream().collect(Collectors.summingInt(Users::getAge));
        System.out.println(collect6);
}

2.8.11、maxBy()/minBy()求最大值/最小值

maxBy()/minBy()根据提供的Comparator,返回stream中的最大或者最小值

//maxBy()/minBy()根据提供的Comparator,返回stream中的最大或者最小值
@Test
public void max(){
		//可以使用默认Comparator.naturalOrder()自然计算,根据字母的大小, 这块使用Comparator.comparing(String::length)值的长度
        Optional<String> collect1 = list1.stream().collect(Collectors.maxBy(Comparator.comparing(String::length)));
        System.out.println(collect1);

        System.out.println("---------------------------");

        //可以使用默认Comparator.naturalOrder()自然计算,根据字母的大小, 这块使用Comparator.comparing(String::length)值的长度
        Optional<String> collect2 = list1.stream().collect(Collectors.minBy(Comparator.comparing(String::length)));
        System.out.println(collect2);

        System.out.println("---------------------------");

        Optional<Users> collect3 = usersList1.stream().collect(Collectors.maxBy(Comparator.comparing(Users::getAge)));
        System.out.println(collect3);

        Optional<Users> collect4 = usersList1.stream().collect(Collectors.minBy(Comparator.comparing(Users::getAge)));
        System.out.println(collect4);
}

2.8.12、groupingBy()分组

groupingBy根据某些属性进行分组,并返回一个Map

//GroupingBy根据某些属性进行分组,并返回一个Map
@Test
public void groupingBy(){
		Map<Integer, Set<String>> collect = list1.stream().collect(Collectors.groupingBy(String::length, Collectors.toSet()));
        collect.forEach((key,value)->{
            System.out.println("key:" +key+" ---- value:"+value);
        });

        System.out.println("---------------------------");

        usersList1.stream().collect(Collectors.groupingBy(Users::getAge)).forEach((key,value)->{
            System.out.println("key:" +key+" ---- value:"+value);
        });
}

2.8.13、partitioningBy()特别分组

PartitioningBy是一个特别的groupingBy,PartitioningBy返回一个Map,这个Map是以boolean值为key,从而将stream分成两部分,一部分是匹配PartitioningBy条件的,一部分是不满足条件的,结果被分成了两部分

//PartitioningBy是一个特别的groupingBy,PartitioningBy返回一个Map,
//这个Map是以boolean值为key,从而将stream分成两部分,一部分是匹配PartitioningBy条件的,一部分是不满足条件的
//结果被分成了两部分
@Test
public void partitioningBy(){
		Map<Boolean, List<String>> collect1 = list1.stream().collect(Collectors.partitioningBy(s -> s.length() > 3));
        collect1.forEach((key,value)->{
            System.out.println("key:" +key+" ---- value:"+value);
        });

        System.out.println("---------------------------");

        Map<Boolean, List<Users>> collect2 = usersList1.stream().collect(Collectors.partitioningBy(u -> u.getAge() > 20));
        collect2.forEach((key,value)->{
            System.out.println("key:" +key+" ---- value:"+value);
        });
}

2.8.14、分组后获取最大值或最小值

//分组后获取最大值或最小值
@Test
public void groupingMaxOrMin(){
    //分组后去最大值
    Map<Integer, Optional<Users>> collect = usersList1.stream().collect(Collectors.groupingBy(Users::getAge, Collectors.maxBy(Comparator.comparing(Users::getId))));

    //分组后去最小值
    Map<Integer, Optional<Users>> collect1 = usersList1.stream().collect(Collectors.groupingBy(Users::getAge, Collectors.minBy(Comparator.comparing(Users::getId))));

    //打印最大值
    collect.forEach((key,value)->{
        System.out.println("key:" +key+" ---- value:"+value);
    });

    System.out.println("-----------------------");

    //打印最小值
    collect1.forEach((key,value)->{
        System.out.println("key:" +key+" ---- value:"+value);
    });
}

2.8.15、分组后重新组装新对象

//分组后重新组装新对象
@Test
public void mapping(){
    Map<Integer, List<String>> collect = usersList1.stream().collect(Collectors.groupingBy(Users::getAge, Collectors.mapping(u -> {
        return u.getName();
    }, Collectors.toList())));

    collect.forEach((key,value)->{
        System.out.println("key:" +key+" ---- value:"+value);
    });
}

2.8.16、单字段进行排序

//单字段进行排序
@Test
public void sort(){
    System.out.println("$$$$$$$$$$$倒序$$$$$$$$$$");
    usersList1.stream().sorted(Comparator.comparing(Users::getAge).reversed()).collect(Collectors.toList()).forEach(System.out::println);

    System.out.println("$$$$$$$$$$$升序$$$$$$$$$$");
    usersList1.stream().sorted(Comparator.comparing(Users::getAge)).collect(Collectors.toList()).forEach(System.out::println);
}

2.8.17、多字段排序,注意:排序的字段不能为空

//多字段排序,注意:排序的字段不能为空
@Test
public void comparator(){
    //手动控制排序,(复制业务的时候,可以采用该方法)
    //1、年龄倒序 2、id升序
    Comparator<Users> usersComparator = Comparator.comparing(Users::getAge, (o1, o2) -> {
        //倒序
        return o2.compareTo(o1);
    }).thenComparing(Users::getId, (o1, o2) -> {
        //升序
        return o1.compareTo(o2);
    });

    List<Users> collect = usersList1.stream().sorted(usersComparator).collect(Collectors.toList());
    collect.forEach(System.out::println);

    System.out.println("#@@@@@@@@@@@@@@@@@@@@@@@@@");


    //* 第二种排倒序方法
    //* Comparator.reverseOrder 倒叙
    //* Comparator.naturalOrder 升叙
    //1、年龄 倒序,2、id 倒序
    Comparator<Users> usersComparator1 = Comparator.comparing(Users::getAge, Comparator.reverseOrder()).thenComparing(Users::getId, Comparator.reverseOrder());

    List<Users> collect1 = usersList1.stream().sorted(usersComparator1).collect(Collectors.toList());

    collect1.forEach(System.out::println);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值