Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作。StreamAPI借助于同样出现的Lambda表达式,极大的提高编程效率和可读性。同时提供串行和并行两种模式操作。 1、Stream流的创建通过 java.util.Collection.stream()方法用集合创建流。 List<String> list = Arrays.asList("hello","world","stream");
//创建顺序流
Stream<String> stream = list.stream();
//创建并行流
Stream<String> parallelStream = list.parallelStream(); 使用java.util.Arrays.stream(T[] arr)方法用数组创建流。 List<String> wordStr= Arrays.asList("word,test,dd,kkk,ffff".split(","));
list = wordStr.stream().map(s -> {
return s.toUpperCase().substring(0,1);
}).collect(Collectors.toList()); 2、无状态(Stateless)操作2.1 filter:筛选,是按照一定的规则校验流中的元素,将符合条件的元素提取到新的流中的操作。 List<String> wordStr= Arrays.asList("word,test,dd,kkk,ffff".split(","));
//查找字符串长度大于3
List<String> filterStr = wordStr.stream().filter(s -> (s.length()>3)).collect(Collectors.toList());
filterStr.forEach(s -> System.out.println(s));
//结果: word test ffff 2.2 映射(map、flatmap、peek) <R> Stream<R> map(Function<? super T, ? extends R> mapper); 代码示例: List<Person> personList = new ArrayList<>();
personList.add(new Person("wjx",33,1));
personList.add(new Person("li",23,2));
List<String> name = personList.stream().map(Person::getName).collect(Collectors.toList());;
System.out.println(name);
//结果:[wjx,li] Person实体类,属性name、age 、id <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) 代码示例: String[] words = new String[]{"hello","world"};
List<String> a1 = Arrays.stream(words)
.map(word -> word.split(""))
.flatMap(Arrays::stream)
.distinct()
.collect(Collectors.toList());
a1.forEach(System.out::print);
//打印结果:helowrd Stream<T> peek(Consumer<? super T> action); 代码示例: Stream<String> stream = Stream.of("hello", "world");
stream.peek(System.out::println); 执行之后,控制台并没有任何输出。流生命周期三个阶段: * 起始生产阶段 * 中间操作会逐一获取元素并进行处理。可有可无。所有中间操作都是惰性的,因此,流在管道中流动之前,任何操作都不会产生任何影响。 * 终端操作。通常分为 最终的消费 (foreach 之类的)和 归纳(collect)两类。还有重要的一点就是终端操作启动了流在管道中的流动 以上代码改为: Stream<String> stream = Stream.of("hello", "world");
stream.peek(System.out::println).collect(Collectors.toList());
//控制台打印内容如下:
hello
world peek和map区别 peek :一般用于不会改变流中元素本身的类型或者只想元素的内部状态时; map:则用于改变流中元素本身类型,即从元素中派生出另一种类型的操作。
代码示例如下,其他类型执行测试: Stream<String> stream = Stream.of("hello", "world");
stream.mapToInt(s->s.length()).forEach(System.out::println);
//输出结果
5
5 3、有状态(stateful)代码示例: List<String> stringList = Arrays.asList("1", "2", "2", "3", "4", "4", "5");
stringList.stream().distinct().forEach(System.out::println);
//1
//2
//3
//4
//5 代码示例: List<String> stringList = Arrays.asList("56", "1", "2", "6", "4", "8", "7");
stringList.stream().sorted().forEach(System.out::println);
// 1
// 2
// 4
// 56
// 6
// 7 代码示例: List<String> stringList = Arrays.asList("1", "2", "3", "4", "8", "7");
stringList.stream().limit(3).forEach(System.out::println);
// 1
// 2
// 3 代码示例: List<String> stringList = Arrays.asList("1", "222", "3", "4", "8", "7");
System.out.println(stringList.stream().anyMatch(s -> {return s.length()>2;}));
// true allMatch:Stream 中全部元素符合传入的 predicate,返回 true; noneMatch:Stream 中没有一个元素符合传入的 predicate,返回 true; findFirst:用于返回满足条件的第一个元素(但是该元素是封装在Optional类中)
代码示例: Stream<Integer> stream = Stream.of(1,4,7,19,8,5,9);
System.out.println("result="+stream.findFirst().get());
//输出
result=1
//当然,我们还可以结合filter处理
System.out.println("result="+stream.filter(s-> s > 3).findFirst().get());
//输出
result=4
代码示例: List<String> strAry = Arrays.asList( "lili", "hali", "Jack", "DaWei", "Jill","Dany");
String result = strAry.parallelStream().filter(s->s.startsWith("J")).findAny().get();
System.out.println("result = " + result);
//输出
result = Jill findAny()操作,返回的元素是不确定的,对于同一个列表多次调用findAny()有可能会返回不同的值。如果是数据较少,串行情况下,一般会返回第一个结果,如果是并行的情况,那就不能确保是第一个。 @reduce一个参数,主要作用 累加、累减,求取最大值、最小值: @Test
public void streamReduceOneTest() throws Exception{
final ArrayList<Integer> list = Lists.newArrayList(1, 3, 5, 2, 4);
// 累加, 1+3+5+2+4
final Optional<Integer> reduce = list.stream().reduce((x, y) -> x + y);
// 累减, 1-3-5-2-4
final Optional<Integer> reduce2 = list.stream().reduce((x, y) -> x - y);
System.out.println("reduce x+y ==>" + reduce.orElse(null));
System.out.println("reduce2 x-y ==>" + reduce2.orElse(null));
// BigDecimal 类型,累加求和
final Optional<BigDecimal> reduce1 = list.stream().map(BigDecimal::new).reduce(BigDecimal::add);
System.out.println("BigDecimal add : "+ reduce1.get());
// 求取 最大值、最小值
final Optional<Integer> reduce3 = list.stream().reduce(BinaryOperator.maxBy((x, y) -> x - y));
final Optional<Integer> reduce4 = list.stream().reduce(BinaryOperator.maxBy((x, y) -> y - x));
System.out.println("max : " + reduce3.get());
System.out.println("min : " + reduce4.get());
} @reduce两个参数,主要作用多了初始值: @Test
public void streamReduceTwoTest() throws Exception {
final ArrayList<Integer> list = Lists.newArrayList(1, 3, 5, 2, 4);
// 2个参数,初始化10,一起累加 , 10+1+3+5+2+4
final Integer reduce = list.stream().reduce(10, (x, y) -> x + y);
// 2个参数,初始化10,一起累减 , 10-1-3-5-2-4
final Integer reduce2 = list.stream().reduce(10, (x, y) -> x - y);
System.out.println("初始化10,reduce x+y ==>" + reduce);
System.out.println("初始化10,reduce2 x-y ==>" + reduce2);
// 累乘, 10*1*3*5*2*4
final Integer reduce1 = list.stream().reduce(10, (x, y) -> x * y);
System.out.println("累积乘法 reduce1 ::: " + reduce1);
// 最大值
final Integer reduce3 = list.stream().reduce(10, BinaryOperator.maxBy((x, y) -> x - y));
System.out.println("最大值: " +reduce3);
} 初始化10,reduce x+y ==>25
初始化10,reduce2 x-y ==>-5
累积乘法 reduce1 ::: 1200
最大值: 10 @reduce三个参数: @Test
public void streamReduceThreeTest() throws Exception {
final ArrayList<Integer> list = Lists.newArrayList(1, 3, 5, 2, 4);
final Integer reduce = list.stream().reduce(20, (x, y) -> x + y, (t, r) -> t - r);
System.out.println("reduce 3个参数:"+reduce);
final ArrayList<String> strList = Lists.newArrayList("aa", "bb", "cc");
// 字符串拼接处理:
/**
* (x, y) -> x.concat(";").concat(y):
* x:初始化 identity 参数 ,
* y: 集合中的每一个元素
*/
final String reduce_three_arg = strList.stream().reduce(String.valueOf("reduce three arg: "), (x, y) -> x.concat(";").concat(y), (x, y) -> x);
System.out.println("reduce 3个参数 22:"+reduce_three_arg);
final String reduce_three_arg2 = strList.stream().reduce(String.valueOf(""), (x, y) -> x.concat(";").concat(y), (x, y) -> x);
System.out.println("reduce 3个参数 2222:"+reduce_three_arg2);
} 输出结果: reduce 3个参数:35
reduce 3个参数 22:reduce three arg: ;aa;bb;cc
reduce 3个参数 2222:;aa;bb;cc @reduce三个参数并行执行 @Test
public void streamReduceThreeParallelTest() throws Exception {
final List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5);
final Integer reduce = list.stream().reduce(0, (x, y) -> x + y, (x, y) -> x * y);
System.out.println(reduce);
// 使用 并行流
final Integer reduce2 = list.parallelStream().reduce(0, (x, y) -> x + y, (x, y) -> x * y);
System.out.println(reduce2);
final Integer reduce3 = list.stream().parallel().reduce(0, (x, y) -> x + y, (x, y) -> x * y);
System.out.println(reduce3);
} 输出结果: 15
120
120
5 reduce总结: 1、reduce 方法:多个数据,合并为一个数据;主要功能如下:累积计算,加减乘除等运算,字符串拼接获取最值,最大值,最小值
2、reduce三个参数区别Stream流总结1、对于流的各种操作还不够熟悉的,可以直接进入方法的源码接口内,如下,是可以查看到类型说明的。
2、并行流stream().parallel()、parallelStream()的使用,须慎重使用!考虑多线程所带来的复杂性!
|