lambda

Java 8 发布的最重要新特性
语法格式

(parameters) -> expression
或
(parameters) ->{ statements; }

以下是lambda表达式的重要特征:

可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。

stream

v256ead609f86c876a0d30d52799c8c35b_720w.png

串行与并行

// 并行
list.parallelStream()
// 串行
list.stream()

基础使用

        List<Student> studentList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Student student = new Student();
            student.setId(i);
            student.setName("s" + i);
            student.setAge(1 + i);
            student.setLanguage("chinese");
            student.setMath("98.5");
            studentList.add(student);
        }
        List<People> list = studentList.stream()
		// filter是过滤的意思
                .filter((Student student) -> {
                    return !(student.getAge() % 3 == 0);
                })
		// map是组装新的集合		
                .map((Student stu) -> {
                    People people = new People();
                    people.setName(stu.getName());
                    people.setAge(stu.getAge());
                    return people;
                }).collect(Collectors.toList());
        for (People p : list) {
            log.info("name = {}", JSON.toJSONString(p));
        }

// list 转 map
Map<Long,Student> studentMap = studentList.stream().collect(Collectors.toMap(Student::getId, a -> a));

Collectors.toMap(dto->key值,dto->dto,(v1,v2)->v1)
在后面添加(v1,v2)->v1 指定选取第一个值 当key值重复的时候。(根据情况而定选取第一个还是第二个)

Student类

@Data
public class Student {
    private int id;
    private String name;
    private int age;
    private String language;
    // 语文成绩
    private String english;
    // 数学成绩
    private String math;
}

People 类

@Data
public class People {
    private String name;
    private int age;
    private String language;
}

介绍两个方法:skip()和limit()

基本概念

skip()方法,用于跳过前面n个元素,然后再返回新的流
limit()方法,它是用于限制流中元素的个数,即取前n个元素,返回新的流

方法skip()的参数n的四种情况:
(1)当n<0时,抛IllegalArgumentException异常;
(2)当n=0时,相当没有跳过任何元素,原封不动、完璧归赵;
(3)当0<n<length时,跳过n个元素后,返回含有剩下的元素的流;
(4)当n>=length时,跳过所有元素,返回空流。

方法limit()的参数n的四种情况:
(1)当n<0时,抛IllegalArgumentException异常;
(2)当n=0时,不取元素,返回空流;
(3)当0<n<length时,取前n个元素,返回新的流;
(4)当n>=length时,取所有元素,原封不动、完璧归赵。

代码分析

skip

List<Integer> result = Stream.of(1, 2, 3, 4, 5, 6)
  .skip(4)
  .collect(Collectors.toList());
List<Integer> expected = asList(5, 6);
assertEquals(expected, result);

limit

List<Integer> result = Stream.of(1, 2, 3, 4, 5, 6)
  .limit(4)
  .collect(Collectors.toList());
List<Integer> expected = asList(1, 2, 3, 4);
assertEquals(expected, result);

组合应用

与subList的替换

subList(startIndex, endIndex)转换成skip(startIndex).limit(endIndex - startIndex)。

List<Integer> list = asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
List<Integer> expected = list.subList(3, 7);
 
List<Integer> result = list.stream()
  .skip(3)
  .limit(7 - 3)
  .collect(Collectors.toList());
assertEquals(expected, result);

分页

获取了第七页数据,每页大小为10。

int pageSize = 10;
int pageIndex = 7;
 
List<Integer> expected = asList(61, 62, 63, 64, 65, 66, 67, 68, 69, 70);
// Stream.iterate(1, i -> i + 1)意思是创建一个无限流的数据源,此处测试用的
List<Integer> result = Stream.iterate(1, i -> i + 1)
  .skip((pageIndex - 1) * pageSize)
  .limit(pageSize)
  .collect(Collectors.toList());
 
assertEquals(expected, result);

定制排序

sorted(Comparator com):定制排序,自定义Comparator排序器

升序

自然排序

list = list.stream().sorted().collect(Collectors.toList());

定制排序

list = list.stream().sorted(Comparator.comparing(Student::getAge)).collect(Collectors.toList());

降序

使用Comparator 提供的reverseOrder() 方法

list = list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
List<类> list; 代表某集合
 
//返回 对象集合以类属性一升序排序
list.stream().sorted(Comparator.comparing(类::属性一));
 
//返回 对象集合以类属性一降序排序 注意两种写法
//先以属性一升序,结果进行属性一降序
list.stream().sorted(Comparator.comparing(类::属性一).reversed());
 //以属性一降序
list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()));
 
//返回 对象集合以类属性一升序 属性二升序
list.stream().sorted(Comparator.comparing(类::属性一).thenComparing(类::属性二));
 
//返回 对象集合以类属性一降序 属性二升序 注意两种写法
 //先以属性一升序,升序结果进行属性一降序,再进行属性二升序
list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二));
 //先以属性一降序,再进行属性二升序
list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()).thenComparing(类::属性二));
 
//返回 对象集合以类属性一降序 属性二降序 注意两种写法
//先以属性一升序,升序结果进行属性一降序,再进行属性二降序
list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二,Comparator.reverseOrder()));
//先以属性一降序,再进行属性二降序
list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()).thenComparing(类::属性二,Comparator.reverseOrder()));
 
//返回 对象集合以类属性一升序 属性二降序 注意两种写法
 //先以属性一升序,升序结果进行属性一降序,再进行属性二升序,结果进行属性一降序属性二降序
list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二).reversed()); 
//先以属性一升序,再进行属性二降序 
list.stream().sorted(Comparator.comparing(类::属性一).thenComparing(类::属性二,Comparator.reverseOrder()));