JDK8 之 Stream流详解
- ==中间操作符:==
- `1.fileter: 根据条件过滤集合数据:`
- `2.distinct:去除集合中重复数据:`
- `3.limit:指定获取集合前x条数据,重新构造一个新的集合:`
- `4.skip:排除集合前x条数据,把后面的数据重新构造一个新的集合:`
- `5.map:对集合中所有元素统一处理`
- `6.flatMap:对集合中所有元素统一处理:`
- `7.对比map与faltMap的区别:`
- `8.peek: 用于不改变流中元素本身 而调用接口或者方法用于传参:`
- `9.map与peek的区别`
- `10.对集合进行排序:`
- ==终止操作符:==
- `1.anyMatch: 判断集合中是否至少存在一个元素满足条件返回true:`
- `2.allMatch: 判断集合中是否所有元素都满足条件:`
- `3.noneMatch: 判断集合中是否所有元素都不满足条件:`
- `4.findAny:返回当前流中任意元素:`
- `5.findFirst: 返回当前流中第一个元素`
- `6.forEach: 遍历流`
- `7.count: 返回流中元素总数`
- `8.collect: 流转换为其他形式(List->Map,List<->Set):`
- `9.reduce: 将流中元素反复结合起来,得到一个值:`
- 链接:[JDK8 Stream流 源代码下载地址]()
概念:
Stream是JDK8 API的新成员,它允许以声明性方式处理数据集合 。
特点:
(1)代码简洁:函数式编程写出的代码简洁且意图明确,使用stream接口让你从此告别for循环。
(2)多核友好:Java函数式编程使得编写并行程序从未如此简单,你需要的全部就是调用一下方法。
流的生命周期:
1.起始生成阶段。
2.中间操作会逐一获取元素并进行处理。 可有可无。所有中间操作都是惰性的,因此,流在管道中流动之前,任何操作都不会产生任何影响。
3.终端操作。通常分为 最终的消费 (foreach 之类的)和 归纳 (collect)两类。还有重要的一点就是终端操作启动了流在管道中的流动。
操作符:
两种:中间操作符、终止操作符
中间操作符:
1.fileter: 根据条件过滤集合数据:
方法 | 含义 | 示例 |
filter | 用于通过设置的条件过滤出元素 | List strings = Arrays.asList(“abc”, “”, “bc”, “efg”, “abcd”,"", “jkl”); |
根据相应业务需求来过滤此集合
/**
* 功能描述:根据条件过滤集合数据
*
* @return : void
*/
@Test
public void fileterTest() {
List<Object> listInt = new ArrayList();//新建个int型集合
//添加参数
listInt.add(1);
listInt.add(2);
listInt.add(0);
listInt.add(4);
listInt.add(3);
//获取此集合的stream流
Stream<Object> stream = listInt.stream();
//问题:获取大于等于1且小于等与3的数并遍历
stream.filter(integer -> (Integer) integer >= 1).filter(integer -> (Integer) integer <= 3).forEach(integer -> System.out.println(integer));
/*
答案:
* 1
* 2
* 3
* */
}
2.distinct:去除集合中重复数据:
方法 | 含义 | 示例 |
distinct | 返回一个元素各异(根据流所生成元素的hashCode和equals方法实现)的流。 | List numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4); |
首先创建JavaBean对象(用来做删除重复对象测试):
必须重写equles()and hasCode()
[如果不重写,就会按照Object的来 Object的比较方式是 ‘==’ 比较地址的]
import java.util.Objects;
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return age == user.age &&
Objects.equals(name, user.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
功能描述:
去除泛型为对象的集合中重复数据
/**
* 功能描述:去除集合中重复数据
*
* @return : void
*/
@Test
public void distinctTest() {
//首先创建出测试对象
User userWhite = new User("小白", 12);
User userWhite2 = new User("小白", 12);
User useBlack = new User("小黑", 12);
//创建集合
List<User> userList = new ArrayList<>();
//为集合添加测试数据
userList.add(userWhite);
userList.add(userWhite2);
userList.add(useBlack);
//获取stream流
Stream<User> stream = userList.stream();
//问题:去掉此集合的重复对象并遍历(这里注意集合里的User对象必须重写equles()and hasCode()[如果不重写,就会按照Object的来 Object的比较方式是 '==' 比较地址的])
stream.distinct().forEach(user -> System.out.println(user));
/*
*答案:
* User{name='小白', age=12}
* User{name='小黑', age=12}
* */
}
3.limit:指定获取集合前x条数据,重新构造一个新的集合:
方法 | 含义 | 示例 |
limit | 会返回一个不超过给定长度的流。 | List strings = Arrays.asList(“abc”, “abc”, “bc”, “efg”, “abcd”,“jkl”, “jkl”); |
指定获取此集合前几条数据(指定数值可大于此集合数据个数:大于此集合个数则返回此集合所有数据)
/**
* 功能描述:指定获取集合前x条数据,重新构造一个新的集合
*
* @return : void
*/
@Test
public void limitTest() {
//创建集合
List<String> stringList = new ArrayList<>();
//创建测试参数
String ab = "ab";
String cd = "cd";
String ef = "ef";
String gh = "gh";
//为集合添加测试数据
stringList.add(ab);
stringList.add(cd);
stringList.add(ef);
stringList.add(gh);
//获取此集合的stream流
Stream<String> stream = stringList.stream();
//问题:获取此集合前两个参数并遍历
stream.limit(2).forEach(string -> System.out.println(string));
/*
* 答案:
* ab
* cd
* */
}
4.skip:排除集合前x条数据,把后面的数据重新构造一个新的集合:
方法 | 含义 | 示例 |
skip | 返回一个扔掉了前n个元素的流。 | List strings = Arrays.asList(“abc”, “abc”, “bc”, “efg”, “abcd”,“jkl”, “jkl”); |
排除集合前x条数据,获取此集合后面的所有数据
/**
* 功能描述:排除集合前x条数据,把后面的数据重新构造一个新的集合
*
* @return : void
*/
@Test
public void skipTest() {
//通过Arrays.asList方法 可以把数组转为List集合
List<Integer> integerList = Arrays.asList(1, 2, 3, 4);
//获取此集合的stream流
Stream<Integer> stream = integerList.stream();
//问题:排除此集合前两个参数,获取后面的所有参数
stream.skip(2).forEach(integer -> System.out.println(integer));
/*
* 答案:
* 3
* 4
* */
}
5.map:对集合中所有元素统一处理
方法 | 含义 | 示例 |
map | 接受一个函数作为参数。这个函数会被应用到每个元素上,并将其映射成一个新的元素(使用映射一词,是因为它和转换类似,但其中的细微差别在于它是“创建一个新版本”而不是去“修改”)。 | List strings = Arrays.asList(“abc”, “abc”, “bc”, “efg”, “abcd”,“jkl”, “jkl”); |
用于改变流中元素,无法调用方法或接口(与flatMap相似)
/**
* 功能描述:对集合中所有元素统一处理
*
* @return : void
*/
@Test
public void mapTest() {
//通过Arrays.asList方法 可以把数组转为List集合
List<String> stringList = Arrays.asList("a", "b", "c", "d");
//获取此集合的stream流
Stream<String> stream = stringList.stream();
//问题:每个数据上都加一个map并遍历
stream.map(string -> string + "map").forEach(sting -> System.out.println(sting));
/*
* 答案:
* amap
* bmap
* cmap
* dmap
* */
}
6.flatMap:对集合中所有元素统一处理:
方法 | 含义 | 示例 |
flatMap | 使用flatMap方法的效果是,各个数组并不是分别映射成一个流,而是映射成流的内容。所有使用map(Arrays::stream)时生成的单个流都被合并起来,即扁平化为一个流。 | List strings = Arrays.asList(“abc”, “abc”, “bc”, “efg”, “abcd”,“jkl”, “jkl”); |
用于改变流中元素,无法调用方法或接口(与map相似)
/**
* 功能描述:对集合中所有元素统一处理
*
* @return : void
*/
@Test
public void flatMap() {
//通过Arrays.asList方法 可以把数组转为List集合
List<String> stringList = Arrays.asList("a", "b", "c", "d");
//获取此集合的stream流
Stream<String> stream = stringList.stream();
//问题:每个数据上都加一个map并遍历
stream.flatMap(s -> Arrays.asList(s + "map").stream()).forEach(s -> System.out.println(s));
/*
* 答案:
* amap
* bmap
* cmap
* dmap
* */
}
7.对比map与faltMap的区别:
map:相当于
put( )
就是直接加进集合
faltMap:相当于putAll( )
将集合拆开再一个个加进另一个集合
/**
* 功能描述:对比map与faltMap的区别
* map:相当于 put 就是直接加进集合
* faltMap:相当于 putAll 将集合拆开再一个个加进另一个集合
*
* @return : void
*/
@Test
public void mapEqulesFlatMap() {
//先创建测试参数
List<String> stringList = Arrays.asList("a.a", "b.b", "c.c","d");
//这里map(s->s.split("\\."))收集之后的结果是Stream<String[]>
stringList.stream().map(s -> s.split("\\.")).forEach(s -> System.out.println(Arrays.toString(s)));
/*
* 打印结果:
* [a, a]
* [b, b]
* [c, c]
* [d]
* */
//这里map(s->s.split("\\."))收集之后的结果是Stream<String>
stringList.stream().flatMap(s -> Arrays.stream(s.split("\\."))).forEach(s -> System.out.println(s));
/*
* 打印结果:
* a
* a
* b
* b
* c
* c
* d
* */
}
8.peek: 用于不改变流中元素本身 而调用接口或者方法用于传参:
方法 | 含义 | 示例 |
peek | 用于不改变流中元素本身 而调用接口或者方法用于传参 | List stringList = Arrays.asList(“a”,“b”,“c”,“d”); |
peek为中间操作符,所以必须要有终止符才会运行相应操做
peek :此方法只能用于把集合内的所有元素当作入参对象来调用别的方法,且无法改变元素本身
/*
* peek为中间操作符,所以必须要有终止符才会运行相应操做
* peek :用于不改变流中元素本身 而调用接口或者方法用于传参
* */
@Test
public void peekTest(){
List<String> stringList = Arrays.asList("a","b","c","d");
//stringList.stream().peek(s -> s+"err").count(); //报错 无法改变流中元素,map可以(但map不能用来调用方法)
stringList.stream().peek(s -> test(s)).count();
stringList.stream().peek(s -> System.out.println(s)).count();
}
/*
* 测试peek (调用此方法)
* */
public void test(String s){
System.err.println(s+"--进入test方法");
}
9.map与peek的区别
peek :用于不改变流中元素本身 而是
把元素当作参数调用接口或方法
map用于改变流中元素
,无法调用方法或接口
/* map与peek的区别:
* peek为中间操作符,所以必须要有终止符才会运行相应操做
* peek :用于不改变流中元素本身 而调用接口或者方法用于传参
* map为中间操作符,所以必须要有终止符才会运行相应操做
* map 用于改变流中元素,无法调用方法或接口
* */
@Test
public void peekEqulesMapTest(){
List<String> stringList = Arrays.asList("a","b","c","d");
//stringList.stream().peek(s -> s+"err").count(); //报错 无法改变流中元素,map可以(但map不能调用别的方法)
stringList.stream().peek(s -> test(s)).forEach(System.out::println);
/*
* a--进入test方法
a
b--进入test方法
b
c--进入test方法
c
d--进入test方法
d
* */
//stringList.stream().map(s -> test(s)).forEach(System.out::println); 报错 map只能改变元素,无法调用方法
stringList.stream().map(s -> s+"map").forEach(System.out::println);
/*
* amap
bmap
cmap
dmap
* */
}
/*
* 测试peek (调用此方法)
* */
public void test(String s){
System.err.println(s+"--进入test方法");
}
10.对集合进行排序:
方法 | 含义 | 示例 |
sorted | 返回排序后的流 | List strings1 = Arrays.asList(“abc”, “abd”, “aba”, “efg”, “abcd”,“jkl”, “jkl”); |
最普通的javaBean:用来做顺序排序用的;
import java.util.Objects;
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return age == user.age &&
Objects.equals(name, user.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
对集合中所有元素进行排序
/**
* 功能描述 : 对集合进行排序
*
* @return : void
*/
@Test
public void sortedTest() {
List<Integer> integerList = Arrays.asList(1, 0, 3, 2);
List<String> stringLetterList = Arrays.asList("abc", "bac", "acb", "cba");
List<String> stringSimplifyList = Arrays.asList("小白", "蓝蓝", "小黑");
List<User> userList = Arrays.asList(new User("小兰", 12), new User("小白", 11));
System.out.println("------数字升序-------");
integerList.stream().sorted().forEach(s -> System.out.println(s));
System.out.println("------数字倒序-------");
integerList.stream().sorted(Comparator.reverseOrder()).forEach(s -> System.out.println(s));
System.out.println("------字符串升序----");
stringLetterList.stream().sorted().forEach(s -> System.out.println(s));
System.out.println("-----字符串倒序----");
stringLetterList.stream().sorted(Comparator.reverseOrder()).forEach(s -> System.out.println(s));
System.out.println("------汉字升序-------");
stringSimplifyList.stream().sorted().forEach(s -> System.out.println(s));
System.out.println("------汉字倒序-------");
stringSimplifyList.stream().sorted(Comparator.reverseOrder()).forEach(s -> System.out.println(s));
System.out.println("------按照对象年龄升序-------");
userList.stream().sorted(Comparator.comparing(User::getAge)).forEach(user -> System.out.println(user));
System.out.println("------按照对象年龄倒序-------");
userList.stream().sorted(Comparator.comparing(User::getAge).reversed()).forEach(user -> System.out.println(user));
/*------数字升序-------
0
1
2
3
------数字倒序-------
3
2
1
0
------字符串升序----
abc
acb
bac
cba
-----字符串倒序----
cba
bac
acb
abc
------汉字升序-------
小白
小黑
蓝蓝
------汉字倒序-------
蓝蓝
小黑
小白
------按照对象年龄升序-------
User{name='小白', age=11}
User{name='小兰', age=12}
------按照对象年龄倒序-------
User{name='小兰', age=12}
User{name='小白', age=11}
*/
}
终止操作符:
1.anyMatch: 判断集合中是否至少存在一个元素满足条件返回true:
方法 | 含义 | 示例 |
anyMatch | 检查是否至少匹配一个元素,返回boolean。 | List strings = Arrays.asList(“abc”, “abd”, “aba”, “efg”, “abcd”,“jkl”, “jkl”); |
检查是否至少匹配一个元素,返回boolean(
只要有一个满足及返回true
,否则返回false)
/**
* 功能描述 : 判断集合中是否至少存在一个元素满足条件返回true
*
* @return : void
*/
@Test
public void anyMatchTest() {
//通过Arrays.asList方法 可以把字符串数组转为List集合
List<String> stringList = Arrays.asList("a", "b", "c");
//获取此集合的stream流并判断是否匹配到s此元素
boolean b = stringList.stream().anyMatch(s -> "a".equals(s));
System.out.println(b);//true[此集合有一个参数匹配到则返回true]
//获取此集合的stream流并判断是否匹配到z此元素
boolean z = stringList.stream().anyMatch(s -> "z".equals(s));
System.out.println(z);//false[此集合有一个参数匹配到则返回true]
}
2.allMatch: 判断集合中是否所有元素都满足条件:
方法 | 含义 | 示例 |
allMatch | 检查是否匹配所有元素,返回boolean。 | List strings = Arrays.asList(“abc”, “abd”, “aba”, “efg”, “abcd”,“jkl”, “jkl”); |
allMatch: 判断集合中是否
所有
元素都满足条件返回true
anyMatch: 判断集合中是否至少存在一个
元素满足条件返回true
/**
* 功能描述 : 判断集合中是否所有元素都满足条件
*
* @return : void
*/
@Test
public void allMatchTest() {
//通过Arrays.asList方法 可以将数值数组转为List集合
List<Integer> integerList = Arrays.asList(0, 2, 4, 6);
//通过stream流 判断此集合是否能被2整除
boolean b = integerList.stream().allMatch(integer -> integer % 2 == 0);
System.out.println(b);//true[当此集合所有参数都符合则返回true]
}
3.noneMatch: 判断集合中是否所有元素都不满足条件:
方法 | 含义 | 示例 |
noneMatch | 检查是否没有匹配所有元素,返回boolean。 | List strings = Arrays.asList(“abc”, “abd”, “aba”, “efg”, “abcd”,“jkl”, “jkl”); |
allMatch: 判断集合中是否
所有
元素都满足条件返回true
anyMatch: 判断集合中是否至少存在一个
元素满足条件返回true
noneMatch: 判断集合中是否所有元素都不满足
条件 返回true
/**
* 功能描述 : 判断集合中是否所有元素都不满足条件
*
* @return : void
*/
@Test
public void noneMatchTest() {
//通过Arrays.asList方法 可以将数值数组转为List集合
List<Integer> integerList = Arrays.asList(1, 3, 5, 7);
//通过stream流 判断此集合是否能被2整除
boolean b = integerList.stream().noneMatch(integer -> integer % 2 == 0);
System.out.println(b);//true[当此集合所有参数都不符合返回true]
}
4.findAny:返回当前流中任意元素:
方法 | 含义 | 示例 |
findAny | 将返回当前流中的任意元素。 | List strings = Arrays.asList(“cv”, “abd”, “aba”, “efg”, “abcd”,“jkl”, “jkl”); |
返回当前流中任意元素 [返回的不是任意元素!(骗子)]
并行流:把一个内容分为多个数据块
,并用不同的线程分别处理每个数据块的流。(返回的几乎是集合中间的元素)
串行流:一整个数据块
, 一个线程处理数据流。(返回的大部分都是第一个元素)
/**
* 功能描述 : 返回当前流中任意元素[返回不了!(骗子)]
* stream:串行流:返回Stream中的第一个元素,但不保证这一点(意思就是有可能返回别的,但我循环好多次都没遇到QAQ就返回集合的第一个)。
* parallelStream:并行流:返回的差不多以此List集合中间的那个数据为主,然后以那个中间数据左右摇摆返回数据(循环1000此 a占绝大部分(961个),剩下的就c(2个)或f(33个),然后就其他的极少极少部分(占5个))
*
* @return : void
*/
@Test
public void findAnyTest() {
//通过Arrays.asList方法 可以将字符串数组转为List集合
List<String> stringList = Arrays.asList("d", "f", "a", "c", "g");
//重复1000次来测试返回元素
for (int i = 0; i < 1000; i++) {
//获取任意元素
String s = stringList.parallelStream().findAny().get();
System.out.println(s);
}
}
5.findFirst: 返回当前流中第一个元素
方法 | 含义 | 示例 |
findFirst | 返回第一个元素 | List strings = Arrays.asList(“cv”, “abd”, “aba”, “efg”, “abcd”,“jkl”, “jkl”); |
顾名思义,返回集合中第一个元素[虽说用findAny()串行流返回的也是此集合的第一个元素,但终归是旁门左道,它主要是返回集合中的任意元素 (虽说我做测试一次 都没见过它返回过除第一个以外的元素QWQ)]
/**
* 功能描述 : 返回当前流中第一个元素
*
* @return : void
*/
@Test
public void findFirstTest() {
//通过Arrays.asList方法 可以将数值数组转为List集合
List<Integer> integerList = Arrays.asList(2, 3, 1, 0);
//获取此集合的第一个元素的Optional容器
Optional<Integer> first = integerList.stream().findFirst();
//判断Optional容器里是否有参数,有则返回true
first.ifPresent(System.out::println);
}
6.forEach: 遍历流
方法 | 含义 | 示例 |
forEach | 遍历流 | List strings = Arrays.asList(“cv”, “abd”, “aba”, “efg”, “abcd”,“jkl”, “jkl”); |
就是相当于我们写的 for循环遍历
效率问题:
如果在循环体中有复杂的业务
、调用远程接口或数据库就用stream
,因为stream是多线程方式并行执行,但是其调用线程池必然会消耗性能,所以简单的操作固然还是for循环效率高。
/**
* 功能描述 : 遍历流
*
* @return : void
*/
@Test
public void foreachTest() {
//通过Arrays.asList方法 可以将字符串数组转为List集合
List<String> stringList = Arrays.asList("小白", "小黑", "小兰", "小花");
//集合遍历
stringList.forEach(System.out::println);
/*
小白
小黑
小兰
小花
* */
}
7.count: 返回流中元素总数
方法 | 含义 | 示例 |
count | 返回流中元素总数。 | List strings = Arrays.asList(“cv”, “abd”, “aba”, “efg”, “abcd”,“jkl”, “jkl”); |
相当于我们写的List.size()
效率问题:
如果在获取个数中有复杂的业务
、调用远程接口或数据库就用stream
,因为stream是多线程方式并行执行,但是其调用线程池必然会消耗性能,所以简单的操作固然还是list.size()效率高。
/**
* 功能描述 : 返回流中元素总数
*
* @return : void
*/
@Test
public void countTest() {
//通过Arrays.asList方法 可以将字符串数组转为List集合
List<Integer> integerList = Arrays.asList(0, 1, 2, 3);
//获取此集合中元素总[integerList.size()也行](也没找到他们俩有啥区别)
long count = integerList.stream().count();
System.out.println(count);
}
8.collect: 流转换为其他形式(List->Map,List<->Set):
方法 | 含义 | 示例 |
collect | 收集器,将流转换为其他形式。 | List strings = Arrays.asList(“cv”, “abd”, “aba”, “efg”, “abcd”,“jkl”, “jkl”); |
将类型相互转换:
Array–>List
List–>Map
List–>Set
/**
* 功能描述 : 流转换为其他形式
*
* @return : void
*/
@Test
public void collectTest() {
System.out.println("------------------list集合----------------------------------");
//通过Arrays.asList方法 可以将字符串数组转为List集合
List<String> stringList = Arrays.asList("小白", "小白", "小黑", "小兰", "小花");
//List转换为Set
Set<String> set = stringList.stream().collect(Collectors.toSet());
System.out.println(set);//[小白, 小黑, 小花, 小兰]
//list转为list
List<String> list = stringList.stream().collect(Collectors.toList());
System.out.println(list);//[小白, 小白, 小黑, 小兰, 小花]
//list转为Map[]
/*
* map传参含义
keyMapper:Key 的映射函数
valueMapper:Value 的映射函数
mergeFunction:当 Key 冲突时,调用的合并方法(最主要!用于key重复时使用)
mapSupplier:Map 构造器,在需要返回特定的 Map 时使用
* */
Map<String, String> map = stringList.stream().collect(Collectors.toMap(s -> s.concat("_name"), s1 -> s1, (s, s1) -> s1 + "重复", HashMap::new));
System.out.println(map);//{小白_name=小白重复, 小黑_name=小黑, 小花_name=小花, 小兰_name=小兰}
System.out.println("------------------set集合----------------------------------");
//创建set集合并赋值
Set<String> stringSet = new HashSet<String>();
stringSet.add("劫");
stringSet.add("烬");
stringSet.add("亚索");
//set转List
List<String> setToList = stringSet.stream().collect(Collectors.toList());
System.out.println(setToList);//[亚索, 劫, 烬]
//set转Map(这里就不用考虑重复问题了)
Map<String, String> setToMap = stringSet.stream().collect(Collectors.toMap(s -> s, s -> s));
System.out.println(setToMap);//{亚索=亚索, 劫=劫, 烬=烬}
}
9.reduce: 将流中元素反复结合起来,得到一个值:
方法 | 含义 | 示例 |
reduce | 可以将流中元素反复结合起来,得到一个值。 | List strings = Arrays.asList(“cv”, “abd”, “aba”, “efg”, “abcd”,“jkl”, “jkl”); |
List<String>
:用符号+
即表示 把此集合的所有元素进行拼接并返回结果
。List<int>
: 用符号+
即表示 数值的加法运算并返回结果
。
用符号*
即表示数值的乘法运算并返回结果
。List<Object>
:必须设置
初始值 identity
/**
* 功能描述 : 将流中元素反复结合起来,得到一个值
* @return : void
*/
@Test
public void reduceTest(){
//--------------泛型为字符串集合测试--------------------
List<String> stringList = Arrays.asList("a","b","c");
String s = stringList.stream().reduce((a, b) -> {
return a + b;
}).get();
System.out.println(s);//abc
//--------------泛型为int集合测试--------------------
List<Integer> integerList = Arrays.asList(1,2,4,3);
Integer integer1 = integerList.stream().reduce((a, b) -> {
return a + b;
}).get();
System.out.println(integer1);//10
Integer integer2 = integerList.stream().reduce(-10,(a, b) -> {
return a + b;
});
System.out.println(integer2);//0
//--------------泛型为对象集合测试--------------------
List<User> userList = new ArrayList<>();
userList.add(new User("小白",12));
userList.add(new User("小黑",13));
userList.add(new User("小倩",12));
Integer reduce = userList.stream().reduce(Integer.valueOf(0) /*初始值 identity*/
, (integer, user) -> integer + user.getAge() /*累加计算 accumulator*/
, (age1, age2) -> age1 + age2 /*第三个参数 combiner*/
);
System.out.println(reduce);//37
//上面获取年龄总和 和下方代码意思一致
Integer total=userList.stream().mapToInt(User::getAge).sum();
System.out.println(total);//37
}