前言:对于简单的数字(list-Int)遍历,普通for循环效率的确比Stream串行流执行效率高(1.5-2.5倍)。但是Stream流可以利用并行执行的方式发挥CPU的多核优势,因此并行流计算执行效率高于for循环。
对于list-Object类型的数据遍历,普通for循环和Stream串行流比也没有任何优势可言,更不用提Stream并行流计算。
虽然在不同的场景、不同的数据结构、不同的硬件环境下。Stream流与for循环性能测试结果差异较大,甚至发生逆转。但是总体上而言:
Stream并行流计算 >> 普通for循环 ~= Stream串行流计算 (之所以用两个大于号,你细品)
数据容量越大,Stream流的执行效率越高。
Stream并行流计算通常能够比较好的利用CPU的多核优势。CPU核心越多,Stream并行流计算效率越高。
https://blog.csdn.net/weixin_37948888/article/details/96995312
findany() 和 findfirst()
2.使用Stream.findAny()
顾名思义,findAny()方法允许您从Stream中查找任何元素。 在寻找元素时使用时不会关注元素顺序。
该方法返回一个Optional实例,如果Stream为空,则该实例为空:
@Test
public void createStream_whenFindAnyResultIsPresent_thenCorrect() {
List<String> list = Arrays.asList("A","B","C","D");
Optional<String> result = list.stream().findAny();
assertTrue(result.isPresent());
assertThat(result.get(), anyOf(is("A"), is("B"), is("C"), is("D")));
}
在非并行操作中,它很可能返回Stream中的第一个元素,但不保证这一点。
为了在处理并行操作时获得最佳性能,也无法返回确定结果:
@Test
public void createParallelStream_whenFindAnyResultIsNotFirst_thenCorrect() {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> result = list
.stream().parallel()
.filter(num -> num < 4).findAny();
assertTrue(result.isPresent());
assertThat(result.get(), anyOf(is(1), is(2), is(3)));
}
- 使用Stream.findFirst()
findFirst()方法查找Stream中的第一个元素。 当您特别需要序列中的第一个元素时,可以使用此方法。
某些流的返回的元素是有确定顺序的,我们称之为 encounter order。这个顺序是流提供它的元素的顺序,比如数组的encounter order是它的元素的排序顺序,List是它的迭代顺序(iteration order),
但是对于HashSet,它本身就没有encounter order。
所以如果流没有encounter order的时候,它返回Stream中的任何元素。
java.util.streams包文档:
Streams may or may not have a defined encounter order. It depends on the source and the intermediate operations.
一个流是否是encounter order主要依赖数据源和它的中间操作。
返回类型也是一个Optional实例,如果Stream也为空,则该实例为空:
@Test
public void createStream_whenFindFirstResultIsPresent_thenCorrect() {
List<String> list = Arrays.asList("A", "B", "C", "D");
Optional<String> result = list.stream().findFirst();
assertTrue(result.isPresent());
assertThat(result.get(), is("A"));
}
findFirst方法的行为在并行方案中也不会更改。 如果是encounter order,则它将始终具有确定性。
findAny()方法返回Stream中的任何元素,而findFirst()方法返回Stream中的第一个元素。
reduce
这个方法的主要作用是把 Stream 元素组合起来。它提供一个起始值(种子),然后依照运算规则(BinaryOperator),和前面 Stream 的第一个、第二个、第 n 个元素组合。从这个意义上说,字符串拼接、数值的 sum、min、max、average 都是特殊的 reduce。例如 Stream 的 sum 就相当于
Integer sum = integers.reduce(0, (a, b) -> a+b); 或
Integer sum = integers.reduce(0, Integer::sum);
也有没有起始值的情况,这时会把 Stream 的前面两个元素组合起来,返回的是 Optional。
清单 15. reduce 的用例
// 字符串连接,concat = “ABCD”
String concat = Stream.of(“A”, “B”, “C”, “D”).reduce("", String::concat);
// 求最小值,minValue = -3.0
double minValue = Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, Double::min);
// 求和,sumValue = 10, 有起始值
int sumValue = Stream.of(1, 2, 3, 4).reduce(0, Integer::sum);
// 求和,sumValue = 10, 无起始值
sumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();
// 过滤,字符串连接,concat = “ace”
concat = Stream.of(“a”, “B”, “c”, “D”, “e”, “F”).
filter(x -> x.compareTo(“Z”) > 0).
reduce("", String::concat);
显示更多
上面代码例如第一个示例的 reduce(),第一个参数(空白字符)即为起始值,第二个参数(String::concat)为 BinaryOperator。这类有起始值的 reduce() 都返回具体的对象。而对于第四个示例没有起始值的 reduce(),由于可能没有足够的元素,返回的是 Optional,请留意这个区别。
使用lambda表达式对List<Map>、List<Model>
的过滤
1.对list
示例:
要求:过滤掉电话相同的map
List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
Map<String, Object> mapStr1 = new HashMap<String, Object>();
mapStr1.put("name", "丽丽");
mapStr1.put("sex", "女");
mapStr1.put("age", 22);
mapStr1.put("tel", "110");
Map<String, Object> mapStr2 = new HashMap<String, Object>();
mapStr2.put("name", "丽丽");
mapStr2.put("sex", "女");
mapStr2.put("age", 23);
mapStr2.put("tel", "120");
Map<String, Object> mapStr3 = new HashMap<String, Object>();
mapStr3.put("name", "丽丽");
mapStr3.put("sex", "女");
mapStr3.put("age", 24);
mapStr3.put("tel", "110");
mapList.add(mapStr1);
mapList.add(mapStr2);
mapList.