17. Lambda

Lambda

只有 SAM接口(函数式接口【类中只有一个抽象方法的接口,可以有其他成员,但是抽象方法只有一个】)才能使用 Lambda 表达式,Lambda 表达式的作用就是简化代码,使代码更整洁。

函数式接口

现在已学的 SAM 接口:

  1. java.lang.Runnable: public void run()
  2. java.lang.Comparable: public int conpareTo(T t)
  3. java.lang.Comparable: public int conpare(T t1, T t2)
  4. java.lang.Iterable: public Iterator iterator()
  5. java.lang.reflect.InvocationHandler: public Object invoke(Object proxy, Method method, Object[] args)
  6. java.io.FileFilter: public boolean accept(File. pathname)

1.8 中建议将符合 SAM 的接口都加上一个 @FunctionalInterface 注解,以上 SAM 接口中如果没有 @FunctionalInterface 注解的,表示以后可能会增加第二个抽象方法,变成非 SAM 接口。这种接口谨慎使用 Lambda 表达式。

JDK 1.8 增加了 java.util.function 包,里面的接口可以分为四大类。包含了大部分可能会遇到的函数式接口。

  1. 消费型接口 (Consumer),这类接口它的抽象方法有参数但是无返回值。
  2. 供给型接口 (Supplier),这类接口它的抽象方法无参数但是有返回值。
  3. 判断型接口 (Predicate),这类接口它的抽象方法有参数,返回值类型为 boolean。
  4. 功能型接口 (Function),这类接口它的抽象方法有参数有返回值。

Lambda 语法

Lambda 表达式式给函数式接口的形参或变量赋值用的,语法格式为:

1
(形参列表) -> {lambda 体}

(形参列表) 就是函数式接口的抽象方法的形参列表。

  1. 如果形参列表是空参,() 是不能省略的。

  2. 如果形参列表非空,并且类型是确定的,那么形参的数据类型是可以省略的。

  3. 如果形参列表非空,并且只有一个形参,并且数据类型也省略了,那么 () 是可以省略的,如果数据类型没有省略, () 也不能省略。

{lambda 体} 就是函数式接口的抽象方法的方法体。

  1. 如果 lambda体 不止一个语句,那么 {} 不能省略,并且每一个语句都要以 ; 结束。
  2. 如果 lambda体 只有一个语句,那么 {}; 可以省略。
  3. 如果该 lambda体 的返回值不是 void,那么lambda体 里面要有 return 语句。如果只有一个返回语句时,{} 和 return 可以省略。

练习1

使用 forEach(Consumer c) 方法遍历 Collection 系列的集合。Collection 自带的 forEach 接收的参数是一个 Consumer,我们只要记住 Consumer 的特征就能写出 lambda 表达式,具体的 Consumer 中的方法是不需要关注的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.itguigu.lambda;

import java.util.ArrayList;

import org.junit.Test;

public class TestLambda {
@Test
public void test1() {
ArrayList<String> userList = new ArrayList<>();
userList.add("zhangsan");
userList.add("lisi");
userList.add("wangwu");
userList.add("zhaoliu");

userList.forEach((String t) -> {System.out.println(t);}); // 未简化版
userList.forEach(t -> System.out.println(t)); // 简化版
}
}

练习2

创建一个 ArrayList 集合,保存学生成员 Student,使用 removeIf(Predicate p) 方法删除成绩不及格的学生。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package com.itguigu.lambda;

import java.util.ArrayList;

import org.junit.Test;

public class TestLamda2 {
@Test
public void test1(){
ArrayList<Student> studentList = new ArrayList<>();
studentList.add(new Student("1", "zhangsan", 99));
studentList.add(new Student("1", "lisi", 59));
studentList.add(new Student("1", "wangwu", 22));

studentList.removeIf((Student s) -> {return (s.getScore() < 60);});
studentList.forEach((Student s) -> {System.out.println(s);});
//Student [id=1, name=zhangsan, score=99]

// 简化写法
studentList.removeIf(s -> (s.getScore() < 60));
studentList.forEach(s -> System.out.println(s));
//Student [id=1, name=zhangsan, score=99]
}
}

class Student {
private String id;
private String name;
private int score;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", score=" + score + "]";
}
public Student(String id, String name, int score) {
super();
this.id = id;
this.name = name;
this.score = score;
}
public Student() {
super();
}
}

练习3

使用 TreeSet 保存学生对象,默认按照学号进行排序,然后在对成绩进行排序,成绩一样在根据学号排序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package com.itguigu.lambda;

import java.util.TreeSet;
import org.junit.Test;

public class TestLamda3 {
@Test
public void test2() {
// 默认按照 分数 进行排序, 创建 TreeSet 的时候可以传入一个 Comparator 比较器
// 以前是匿名内实现的,现在使用 Lambda 实现。
TreeSet<EnglishStudent> englishStudentList = new TreeSet<>((EnglishStudent e1, EnglishStudent e2) -> {return e1.getScore() - e2.getScore();}) ;
englishStudentList.add(new EnglishStudent(1, "zhangsan", 99));
englishStudentList.add(new EnglishStudent(2, "lisi", 89));
englishStudentList.add(new EnglishStudent(3, "wangwu", 99));
englishStudentList.forEach(f-> System.out.println(f));
System.out.println("test2");
/**
EnglishStudent [id=2, name=lisi, score=89]
EnglishStudent [id=1, name=zhangsan, score=99]
test2
*/
// 这里只打印了两条记录,原因是 TreeSet 判断元素是否重复不是看 hashCode 方法和 equals 方法
// 而是看实现的比较大小的方法。因为现在比较成绩,有两个人成绩相同,所以就少显示一条数据
// 我们可以用过先比较成绩,成绩相同在比较 id 进行排序
TreeSet<EnglishStudent> englishStudentList2 = new TreeSet<>((e1, e2) -> e1.getScore() == e2.getScore()?e1.getId() - e2.getId(): e1.getScore() - e2.getScore()) ;
englishStudentList2.add(new EnglishStudent(1, "zhangsan", 99));
englishStudentList2.add(new EnglishStudent(2, "lisi", 89));
englishStudentList2.add(new EnglishStudent(3, "wangwu", 99));
englishStudentList2.forEach(f-> System.out.println(f));
/**
EnglishStudent [id=2, name=lisi, score=89]
EnglishStudent [id=1, name=zhangsan, score=99]
EnglishStudent [id=3, name=wangwu, score=99]
*/
}

@Test
public void test1() {
// 默认按照 ID 进行排序
TreeSet<EnglishStudent> englishStudentList = new TreeSet<>();
englishStudentList.add(new EnglishStudent(1, "zhangsan", 99));
englishStudentList.add(new EnglishStudent(2, "lisi", 89));
englishStudentList.add(new EnglishStudent(3, "wangwu", 99));
englishStudentList.forEach(f-> System.out.println(f));
System.out.println("test1");
/**
EnglishStudent [id=1, name=zhangsan, score=99]
EnglishStudent [id=2, name=lisi, score=89]
EnglishStudent [id=3, name=wangwu, score=99]
test1
*/
}
}

class EnglishStudent implements Comparable<EnglishStudent>{
private int id;
private String name;
private int score;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public EnglishStudent(int id, String name, int score) {
super();
this.id = id;
this.name = name;
this.score = score;
}
public EnglishStudent() {
super();
}
@Override
public int compareTo(EnglishStudent o) {
// 默认按照 ID 进行排序
return this.id - o.id;
}
@Override
public String toString() {
return "EnglishStudent [id=" + id + ", name=" + name + ", score=" + score + "]";
}
}

练习4

创建一个 HashMap,键和值都是 String 类型,使用 Map 的 void forEach(BiConsumer<? super K, ? super V> action) 这个方法遍历显示 Map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.itguigu.lambda;

import java.util.HashMap;

import org.junit.Test;

public class TestLamb4 {
@Test
public void test() {
HashMap<String, String> map = new HashMap<>();
map.put("zhangsan", "xxx");
map.put("lisi", "yyy");
map.put("wangwu", "zzz");

// 未简写
map.forEach((String k, String v) -> {System.out.println(k + ":" + v);});

// 简写
map.forEach((k, v) -> System.out.println(k + ":" + v));
}
}

练习5

声明一个 Book 图书类,属性有编号,书名,作者,价格。创建一个 BookService 管理类,里面有一个集合 ArrayList<Book> 用来存储书籍。现要求在 BookService 中创建一个 query 方法 public ArrayList<Book> query(Predicate<Book> p){} 可以实现以下功能:

  1. 查询指定 id 的图书
  2. 查询某个作者的图书
  3. 查询某个价格范围的图书
  4. 查询书名包含某个字的图书
  5. 查询所有的图书
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package com.itguigu.lambda;

import java.util.ArrayList;
import java.util.function.Predicate;

public class TestLambda5 {
public static void main(String[] args) {
BookService bookService = new BookService();
// 1. 查询指定 id 的图书
ArrayList<Book> query = bookService.query((Book b) -> {return (b.getId() == 1);});
query.forEach(b -> System.out.println(b));
System.out.println("============ 1 ============");

// 2. 查询某个作者的图书
ArrayList<Book> query2 = bookService.query(b -> b.getAuthor() == "罗贯中");
query2.forEach(b -> System.out.println(b));
System.out.println("============ 2 ============");

// 3. 查询某个价格范围的图书
ArrayList<Book> query3 = bookService.query(b -> b.getPrice() > 10);
query3.forEach(b -> System.out.println(b));
System.out.println("============ 3 ============");

// 4. 查询书名包含某个字的图书
ArrayList<Book> query4 = bookService.query(b -> b.getName().contains("三"));
query4.forEach(b -> System.out.println(b));
System.out.println("============ 4 ============");

// 5. 查询所有的图书
ArrayList<Book> query5 = bookService.query(b -> true);
query5.forEach(b -> System.out.println(b));
System.out.println("============ 5 ============");
/**
Book [id=1, name=三国演义, author=罗贯中, price=99.0]
============ 1 ============
Book [id=1, name=三国演义, author=罗贯中, price=99.0]
============ 2 ============
Book [id=1, name=三国演义, author=罗贯中, price=99.0]
Book [id=2, name=西游记, author=吴承恩, price=88.0]
Book [id=3, name=红楼梦, author=曹雪芹, price=22.0]
============ 3 ============
Book [id=1, name=三国演义, author=罗贯中, price=99.0]
============ 4 ============
Book [id=1, name=三国演义, author=罗贯中, price=99.0]
Book [id=2, name=西游记, author=吴承恩, price=88.0]
Book [id=3, name=红楼梦, author=曹雪芹, price=22.0]
============ 5 ============
*/
}
}

class BookService {
private ArrayList<Book> BookList;
public BookService() {
BookList = new ArrayList<>();
BookList.add(new Book(1, "三国演义", "罗贯中", 99.0));
BookList.add(new Book(2, "西游记", "吴承恩", 88.0));
BookList.add(new Book(3, "红楼梦", "曹雪芹", 22.0));
}

// Predicate 为判断型接口,所以在传入 lambda 的时候需要有参数,但是不需要返回值
public ArrayList<Book> query(Predicate<Book> predicate){
ArrayList<Book> resultList = new ArrayList<>();
// 循环遍历图书,判断图书是否满足传入的 lambda 条件
for (Book book : BookList) {
if (predicate.test(book)) {
resultList.add(book);
}
}
return resultList;
}
}

class Book{
// 编号,书名,作者,价格
private int id;
private String name;
private String author;
private Double price;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
@Override
public String toString() {
return "Book [id=" + id + ", name=" + name + ", author=" + author + ", price=" + price + "]";
}
public Book(int id, String name, String author, Double price) {
super();
this.id = id;
this.name = name;
this.author = author;
this.price = price;
}
}

方法引用和构造器引用

当 lambda 表达式的 lambda体满足一些情况时,可以使用方法引用和构造器引用再次简化。

  1. 当 lambda 体是通过调用一个先有的类,对象的先有的方法来完成功能时。
  2. 并且这个方法的形参列表和返回值类型与该 lambda 表达式所赋值的函数式接口的抽象方法的形参列表和返回值类型对应。

形式

  1. 对象::实例方法名
  2. 类名::静态方法名
  3. 类名::实例方法名
  4. 类名::new —> 构造器引用
  5. 数组类型::new. —> 特殊的构造器引用,数组的构造器引。用

举例,对象::实例方法名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.itguigu.lambda;

import java.util.ArrayList;

import org.junit.Test;

public class TestLambda {
@Test
public void test1() {
ArrayList<String> userList = new ArrayList<>();
userList.add("zhangsan");
userList.add("lisi");
userList.add("wangwu");
userList.add("zhaoliu");

userList.forEach((String t) -> {System.out.println(t);}); // 未简化版
userList.forEach(t -> System.out.println(t)); // 简化版

/**
* 上面的 lambda 表达式是通过一个现有的方法完成的,即通过调用 out 对象的 println 来完成的
* 并且 out 对象的 println 方法只需形式参数 t,且无返回值。 void println(T t)
* Consumer 的抽象方法也是无返回值,只需形式参数 t。void xxx(T t)
* 所以可以改为方法引用
*/

userList.forEach(System.out::println);
}
}

Stream API

Stream 的特点:1. Stream 本身不负责存储数据,只负责处理数据。 2. Stream 不会改变原对象,每次处理都会返回一个新的 Stream 3. Stream 操作是延迟的,只有到需要结果的时候才会真正的执行。

操作 Stream 的步骤

1. 建立一个 Stream 数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package com.itguigu.lambda;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.Stream;

import org.junit.Test;

public class TestStream {
@Test
public void test1() {
// 使用数组工具类 java.util.Arrays 中的 static <T> Stream<T> stream(T[] array) 创建
String[] arr = {"hello", "test"};
// 创建 stream
Stream<String> stream = Arrays.stream(arr);
// 遍历就终结了stream
stream.forEach(t->System.out.println(t));
}

@Test
public void test2() {
// 用集合创建 Stream
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("zhangsan");
arrayList.add("lisi");

// 创建 stream
Stream<String> stream = arrayList.stream();
// 遍历就终结了stream
stream.forEach(t->System.out.println(t));
}

@Test
public void test3() {
// 使用 Stream 的 of 方法创建
Stream<String> stream = Stream.of("zhangsan", "lisi", "wangwu");
// 遍历就终结了stream
stream.forEach(t->System.out.println(t));
}

@Test
public void test4() {
// 使用 Stream 的 generate 方法创建无限流 (传入供给形接口的 lambda 表达式)
Stream<Double> stream = Stream.generate(() -> Math.random());
// 不断的产生随机数
stream.forEach(t->System.out.println(t));
}

@Test
public void test5() {
/**
* t 是流中的数据,第一个数据是1,即种子
* 在 1 的基础上不断的迭代
* 数据流中的数据就成了 1,3,5,7,9。。。
*/
Stream<Integer> stream = Stream.iterate(1, t -> t+2);
// 遍历就终结了stream
stream.forEach(t->System.out.println(t));
}
}
2. 处理数据(中间过程)

filter(Predicate t) 按照 p 的条件进行过滤,Predicate 接口为判断形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package com.itguigu.lambda;

import java.util.ArrayList;
import java.util.stream.Stream;

import org.junit.Test;

public class TestFilter {
@Test
public void test1() {
ArrayList<Employee> arrayList = new ArrayList<>();
arrayList.add(new Employee("zhangsan", 1));
arrayList.add(new Employee("lisi", 2));
arrayList.add(new Employee("wangwu", 3));


Stream<Employee> stream = arrayList.stream();
// 过滤 Id 大于等于2的员工
Stream<Employee> filter = stream.filter((t) -> t.getId() >= 2);
filter.forEach(System.out::println);
}
}

class Employee{
private String name;
private int id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public Employee(String name, int id) {
super();
this.name = name;
this.id = id;
}
@Override
public String toString() {
return "Employee [name=" + name + ", id=" + id + "]";
}
}

distinct 去重

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package com.itguigu.lambda;

import java.util.ArrayList;
import java.util.stream.Stream;

import org.junit.Test;

public class TestFilter {
@Test
public void test1() {
ArrayList<Employee> arrayList = new ArrayList<>();
arrayList.add(new Employee("zhangsan", 1));
arrayList.add(new Employee("zhangsan", 1));
arrayList.add(new Employee("wangwu", 3));


Stream<Employee> stream = arrayList.stream();
// 去重,distinct 依赖 equals 方法,所以一定要重新 equals 和 hashcode 方法,
// 不然和 == 一样,比较的是地址
Stream<Employee> filter = stream.distinct();
filter.forEach(System.out::println);
}
}

class Employee{
private String name;
private int id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public Employee(String name, int id) {
super();
this.name = name;
this.id = id;
}
@Override
public String toString() {
return "Employee [name=" + name + ", id=" + id + "]";
}
}

limit(long Maxsize) 去流中的前 Maxsize 个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.itguigu.lambda;

import java.util.Arrays;
import java.util.stream.IntStream;

import org.junit.Test;

public class TestFilter {
@Test
public void test1() {
int[] arr = {1,2,3,4,5,6,7,8};
IntStream stream = Arrays.stream(arr);
// limit
IntStream limit = stream.limit(3);
limit.forEach(System.out::println);

// 或者直接连起来写
IntStream stream2 = Arrays.stream(arr);
stream2.limit(3).forEach(System.out::println);
}
}

skip(long n) 跳过前 n 个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.itguigu.lambda;

import java.util.Arrays;
import java.util.stream.IntStream;

import org.junit.Test;

public class TestFilter {
@Test
public void test1() {
int[] arr = {1,2,3,4,5,6,7,8};
IntStream stream = Arrays.stream(arr);
// skip
IntStream limit = stream.skip(3);
limit.forEach(System.out::println);

// 或者直接连起来写
IntStream stream2 = Arrays.stream(arr);
stream2.skip(3).forEach(System.out::println);
}
}

peek(Consumer action) 对流中的数据执行 Consumer 接口的 action 操作,Consumer 接口为消费形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.itguigu.lambda;

import java.util.Arrays;
import java.util.stream.IntStream;

import org.junit.Test;

public class TestFilter {
@Test
public void test1() {
int[] arr = {1,2,3,4,5,6,7,8};
IntStream stream = Arrays.stream(arr);
// 在 peek 中输出
IntStream peek = stream.peek((t) -> System.out.println(t));
// count 为终结操作
long count = peek.count();
// 打印 peek 的总数
System.out.println(count);
}
}

sorted(Comparator com)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.itguigu.lambda;

import java.util.stream.Stream;

import org.junit.Test;

public class TestFilter {
@Test
public void test1() {
Stream.of(1,2,3,4,5,6,7,8,8,024,2424,65,456)
.sorted((t1, t2) -> Integer.compare(t2, t1)) // 倒序
.forEach(System.out::println);

Stream.of(1,2,3,4,5,6,7,8,8,024,2424,65,456)
.sorted() // 正序
.forEach(System.out::println);
}
}

map(Function f) 对流中的每一个元素,都映射 f 指定的操作,Function 接口为功能形,有参有返回值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.itguigu.lambda;

import java.util.stream.Stream;

import org.junit.Test;

public class TestFilter {
@Test
public void test1() {
Stream.of(1,2,3,4,5,6,7,8,8,024,2424,65,456)
.map(t -> t + 2). // 对每个元素都进行 +2 操作
forEach(System.out::println);
}
}

flatMap(Function f)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.itguigu.lambda;

import java.util.stream.Stream;

import org.junit.Test;

public class TestFilter {
@Test
public void test1() {
Stream<String> stream = Stream.of("zhangsan,lisi,wangwu", "xiaoer,renren");
// 使用 flatMap,将进行 split 操作得到的数组再变成一个 split
Stream<String> flatMap = stream.flatMap(t -> Stream.of(t.split(",")));
flatMap.forEach(System.out::println);
/**
* zhangsan lisi wangwu xiaoer renren
*/
}
}
3. 取结果(终结)

forEach, count, max【求最大值】, min【求最小值】, allMatch【是否所有的都匹配】, anyMatch【是否有一个匹配】, noneMatch【是否都不匹配】, collect 【】等操作等会终结流。一旦流被终结就不能再使用了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.itguigu.lambda;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.junit.Test;

public class TestFilter {
@Test
public void test1() {
// 获取最大值
Optional<Integer> max = Stream.of(2,456,567,678,24,1,13,13).max((t1, t2) -> Integer.compare(t1, t2));
System.out.println(max);

// 判断数据是否都是偶数
boolean allMatch = Stream.of(2,456,567,678,24,1,13,13).allMatch(t -> t%2==0);
System.out.println(allMatch);

// 将过滤后符合的数据重新收集到一个 list 集合中
List<Integer> collect = Stream.of(2,456,567,678,24,1,13,13).filter(t -> t > 5).collect(Collectors.toList());
System.out.println(collect);
}
}