函数式编程part3-Stream流
3.1 概述
Java8的Stream使用的是函数式编程模式,
如同它的名字一样,它可以被用来对集合或数组进行链状流式的操作。可以更方便的让我们对集合或数组操作。
3.3 快速入门
3.3.1 需求
//打印所有年龄小于18的作家的名字,并且要注意去重
List<Author> authors = getAuthors();
authors.
stream()//把集合转换成流
.distinct()//先去除重复的作家
.filter(author -> author.getAge()<18)//筛选年龄小于18的
.forEach(author -> System.out.println(author.getName()));//遍历打印名字
3.4 常用操作
3.4.1 创建流
List<Author> authors = getAuthors();
Stream<Author> stream = authors.stream();
Integer[] arr = {1,2,3,4,5};
Stream<Integer> stream = Arrays.stream(arr);
Stream<Integer> stream2 = Stream.of(arr);
Map<String,Integer> map = new HashMap<>();
map.put("蜡笔小新",19);
map.put("黑子",17);
map.put("日向翔阳",16);
Stream<Map.Entry<String, Integer>> stream = map.entrySet().stream();
List<Author> authors = getAuthors();
authors.stream()
.filter(author -> author.getName().length()>1)
.forEach(author -> System.out.println(author.getName()));
List<Author> authors = getAuthors();
authors
.stream()
.map(author -> author.getName())
.forEach(name->System.out.println(name));
List<Author> authors = getAuthors();
authors.stream()
.distinct()
.forEach(author -> System.out.println(author.getName()));
sorted()
使用匿名内部类形式去调用Comparable的compare方法,最终结果经过Lambda如下
```java
List<Author> authors = getAuthors();
// 对流中的元素按照年龄进行降序排序,并且要求不能有重复的元素。
authors.stream()
.distinct()
.sorted((o1, o2) -> o2.getAge()-o1.getAge())
.forEach(author -> System.out.println(author.getAge()));
```
可以设置流的最大长度,超出的部分将被抛弃。
skip()
跳过流中的前n个元素,返回剩下的元素
forEach()
对流中的元素进行遍历操作,我们通过传入的参数去指定对遍历到的元素进行什么具体操作。
输出所有作家的名字
// 输出所有作家的名字
List<Author> authors = getAuthors();
authors.stream()
.map(author -> author.getName())
.distinct()
.forEach(name-> System.out.println(name));
List<Author> authors = getAuthors();
long count = authors.stream()
.flatMap(author -> author.getBooks().stream())
.distinct()
.count();
System.out.println(count);
List<Author> authors = getAuthors();
Optional<Integer> max = authors.stream()
.flatMap(author -> author.getBooks().stream())
.map(book -> book.getScore())
.max((score1, score2) -> score1 - score2);
Optional<Integer> min = authors.stream()
.flatMap(author -> author.getBooks().stream())
.map(book -> book.getScore())
.min((score1, score2) -> score1 - score2);
System.out.println(max.get());
System.out.println(min.get());
把当前流转换成一个集合。
获取一个存放所有作者名字的List集合。
.collect(Collectors.toList());
查找与匹配
anyMatch()
可以用来判断是否有任意符合匹配条件的元素,返回结果为boolean类型。
判断是否有年龄在29以上的作家
boolean flag = authors.stream()
.anyMatch(author -> author.getAge() > 29);
allMatch()
可以用来判断是否都符合匹配条件,结果为boolean类型。如果都符合结果为true,否则结果为false。
判断是否所有的作家都是成年人
boolean flag = authors.stream()
.allMatch(author -> author.getAge() >= 18);
noneMatch()
可以判断流中的元素是否都不符合匹配条件。如果都不符合结果为true,否则结果为false
判断作家是否都没有超过100岁的。
boolean b = authors.stream()
.noneMatch(author -> author.getAge() > 100);
findFirst()
获取流中的第一个元素。
reduce归并
对流中的数据按照你指定的计算方式计算出一个结果(缩减操作)
reduce的作用是把Stream中的元素组合起来
我们可以传入一个一个初始值,它会按照我们的计算方式依次拿流中的元素和在初始化值的基础上进行计算,计算后再和后面的元素计算
内部计算方式:
T result = 初始化值;
for(T element : this stream) 遍历流获取元素
result = accumulator.apply(result,element) 调用对象的某方法,传入result和当前遍历到的元素值
return result;
——————————例————————————
使用reduce求所有作者年龄的和
.reduce(0, (result, element) -> result + element);
使用reduce求所有作者中年龄的最大值
.reduce(Integer.MIN_VALUE, (result, element) -> result < element ? element : result);
使用reduce求所有作者中年龄的最小值
.reduce(Integer.MAX_VALUE, (result, element) -> result > element ? element : result);
reduce(一个参数)的重载形式内部计算:
boolean foundAny = false; T result = null; for (T element : this stream) { if (!foundAny) { foundAny = true; result = element; } else result = accumulator.apply(result, element); } return foundAny ? Optional.of(result) : Optional.empty();
3.5 注意事项
-
惰性求值(如果没有终结操作,没有中间操作是不会得到执行的),我们需要终结操作
-
流是一次性的(一旦一个流对象经过一个终结操作后。这个流就不能再被使用)
-
不会影响原数据(我们在流中可以多数据做很多处理。但是正常情况下是不会影响原来集合中的元素的。这往往也是我们期望的)