Java Stream
概述
- JDK : 1.8
总结
- 概念定义1:
- Stream 是增强型的 Iterator
- Stream 是对集合(Collection)对象功能的增强,专注于对集合对象进行便利、高效的聚合操作、大批量数据操作
- 特点总结:
- 无存储:Stream不是一种数据结果,只是数据的一种视图
- 无修改:Stream任何修改都不会影响原来的数据源
- 无限制:Stream 数据源本身可以是无限大小
- 一次消费:单向处理,Stream一次遍历后即会失效,再次处理需要再次遍历
- 堕式执行:Stream上的操作并不会立即执行,而是等到使用结果时才会执行;节省执行时间
- 可并行化:并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程;并行操作依赖于 Java7 中引入的 Fork/Join 框架(JSR166y)来拆分任务和加速处理过程
- 无法索引:不支持通过数组下标访问集合元素的方式
- 无顺序性:输出结果不保证与原有集合中元素顺序相同
- 操作类型
- 中间操作:
- 一个Stream后跟0或多个中间操作,过滤或排序等操作生成新的Stream
- 惰性操作:仅仅只是方法调用而并未实际对流进行处理,只有在获取结果时才会执行
- 最终操作:
- 一个Stream只有一个最终操作,只有执行到最终操作时才会进行流的处理
- 中间操作:
操作
-
Stream 构建2
/** * Stream 初始化 */ private static void streamInit(){ // 数值型 Stream Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8); Stream<Long> longStream = Stream.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L); Stream<Float> floatStream = Stream.of(1f, 2f, 3f, 4f, 5f, 6f, 7f, 8f); // 三种基本数值型提供了对应的Stream IntStream intStream = IntStream.of(1,2,3,4,5,6,7,8); LongStream longStreams = LongStream.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L); DoubleStream doubleStream = DoubleStream.of(1f,2f,3f,4f,5f,6f,7f,8f); // 字符串 Stream<String> stringStream = Stream.of("a", "b", "c", "d", "e", "f", "g", "h"); // 数组 Stream<Integer> integerArrayStream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8); Arrays.stream(new int[]{1,2,3,4,5,6}); // 集合 Stream<List<Integer>> listStream = Stream.of(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8)); // 生成器 Stream.generate(Math::random); }
/** * Stream 数值型Stream 构造 */ private static void streamNumberBuild(){ // 全部数据 IntStream.of(1,2,3,4,5).forEach(System.out::print); // [ )区间 IntStream.range(1,5).forEach(System.out::print); // [ ]区间 IntStream.rangeClosed(1,5).forEach(System.out::print); // 连接 IntStream.concat(IntStream.range(1,5),IntStream.rangeClosed(5,10)).forEach(System.out::print); }
/** * 集合工具类中提供默认构造Stream方法 */ public interface Collection<E> extends Iterable<E> { default Stream<E> stream() { return StreamSupport.stream(spliterator(), false); } }
public class Arrays { public static <T> Stream<T> stream(T[] array) { return stream(array, 0, array.length); } }
-
Stream map()
/** * Stream map 数据映射,将输入流通过某种规则变更后改为输出流 *map 将对于Stream中包含的元素使用给定的转换函数进行转换操作,新生成的Stream只包含转换生成的元素 *flatMap 对Stream 进行操作 */ private static void streamMap(){ // map 转换结果 1对1映射 // 字符串大小写转换 List<String> strings = Arrays.asList("a", "b", "c"); strings.stream().map(String::toUpperCase).collect(Collectors.toList()).forEach(System.out::print); // 数据平方值 Arrays.asList(1,2,3,4,5).stream().map(n->n*n).collect(Collectors.toList()).forEach(System.out::print); // map 转换结果 1对多映射 Stream<List<Integer>> stream = Stream.of(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6 ), Arrays.asList(7, 8, 9)); stream.flatMap(a -> a.stream()).forEach(System.out::print); }
-
Stream limit()、skip()
/** * Stream * limit 只输出前 n 个 * skip 只过滤前 n 个 */ private static void streamLimitAndSkip(){ Arrays.asList(1,2,3,4,5,6,7,8,9).stream().limit(3).forEach(System.out::print); Arrays.asList(1,2,3,4,5,6,7,8,9).stream().skip(3).forEach(System.out::print); }
-
Stream peek()、forEach()
/** * Stream peek:通过 peek 可以查看多次转换结果 * peek方法生成一个包含原Stream的所有元素的新Stream * Stream forEach: 不改变元素,无法通过break/continue/return终止,只能输出一次 */ private static void streamPeek(){ Arrays.asList(1,2,3,4,5,6,7,8,9).stream().filter(a -> a > 3).peek(a -> System.out.println("a:"+a)) .map(a -> a * a).peek(a -> System.out.print("a:"+a)).collect(Collectors.toList()) .forEach(System.out::print); }
-
Stream optional()
/** * Stream Optional */ private static void streamOptional(){ String str = null ; System.out.println(Optional.ofNullable(str).map(String::length).orElse(-1)); }
-
Stream Iterate()
private static void streamIterator(){ Stream.iterate(0,a -> a+2).limit(10).collect(Collectors.toList()).forEach(System.out::print); }
-
Stream match()
/**
* Stream match
* allMatch 所有全部符合
* anyMatch 存在符合元素
* noneMatch 全部不符合
*/
private static void streamMatch(){
// 两个集合取交集
final List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
boolean b = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8).stream().anyMatch(a -> integerList.contains(a));
System.out.println(b);
// Lambda 表达式内部使用的外部参数,引用值而非变量,相当于 final 修饰
// 当变量重新赋值时会提示便于错误
// 如果 Lambda 表达式内部使用某个变量的值,而该变量后续需要重新赋值,需要对该值进行拷贝,避免异常
System.out.println(Arrays.asList(1, 3, 5, 7, 9).stream().noneMatch(a -> integerList.contains(a)));
}
- Stream collect3
-
collector.group
/** * Stream group */ private static void streamGroup(){ // 将数组分为奇数偶数两个集合 Map<Boolean, List<Integer>> collect = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream().collect(Collectors.partitioningBy(a -> a % 2 == 0)); collect.forEach( (a,b) -> System.out.println("key:"+a+",value:"+b.toString())); // 将List转为Map List<OrderGoods> orderGoodsList = generateOrderGoodsList(); Map<String, List<OrderGoods>> orderGoodsGroupMap = orderGoodsList.stream().collect(Collectors.groupingBy (orderGoods -> String.format("%d_%d_%d_%d", orderGoods.getGoodsId(), orderGoods.getGroupGoodsId(), orderGoods.getIsGift(), orderGoods.getSellerId()))); orderGoodsGroupMap.forEach((a,b) -> System.out.println("key:"+a+",value:"+b.toString())); } private static List<OrderGoods> generateOrderGoodsList(){ OrderGoods orderGoods1 = new OrderGoods(); orderGoods1.setGoodsId(1); orderGoods1.setGroupGoodsId(1); orderGoods1.setIsGift(0); orderGoods1.setSellerId(1); orderGoods1.setOrderId(1); OrderGoods orderGoods2 = new OrderGoods(); orderGoods2.setGoodsId(1); orderGoods2.setGroupGoodsId(1); orderGoods2.setIsGift(1); orderGoods2.setSellerId(1); orderGoods2.setOrderId(2); OrderGoods orderGoods3 = new OrderGoods(); orderGoods3.setGoodsId(1); orderGoods3.setGroupGoodsId(1); orderGoods3.setIsGift(0); orderGoods3.setSellerId(1); orderGoods3.setOrderId(1); OrderGoods orderGoods4 = new OrderGoods(); orderGoods4.setGoodsId(1); orderGoods4.setGroupGoodsId(1); orderGoods4.setIsGift(0); orderGoods4.setSellerId(1); orderGoods4.setOrderId(2); OrderGoods orderGoods5 = new OrderGoods(); orderGoods5.setGoodsId(1); orderGoods5.setGroupGoodsId(1); orderGoods5.setIsGift(0); orderGoods5.setSellerId(1); orderGoods5.setOrderId(2); return Arrays.asList(orderGoods1,orderGoods2,orderGoods3,orderGoods4,orderGoods5); }
public class OrderGoods { private Integer orderId ; private Integer goodsId ; private Integer groupGoodsId ; private Integer isGift ; private Integer sellerId ; public Integer getOrderId() { return orderId; } public void setOrderId(Integer orderId) { this.orderId = orderId; } public Integer getGoodsId() { return goodsId; } public void setGoodsId(Integer goodsId) { this.goodsId = goodsId; } public Integer getGroupGoodsId() { return groupGoodsId; } public void setGroupGoodsId(Integer groupGoodsId) { this.groupGoodsId = groupGoodsId; } public Integer getIsGift() { return isGift; } public void setIsGift(Integer isGift) { this.isGift = isGift; } public Integer getSellerId() { return sellerId; } public void setSellerId(Integer sellerId) { this.sellerId = sellerId; } @Override public String toString() { return "goodsId:"+goodsId+",groupId:"+groupGoodsId+",isGift:"+isGift+",sellerId:"+sellerId+",orderId:"+orderId; } }
-
collectors 集合
/** * Stream collect 集合常用操作 */ private static void streamCollectOperation(){ // 平均值 System.out.println(Arrays.asList(1, 2, 3, 4, 5).stream().collect(Collectors.averagingInt(value -> value))); // 最大值 System.out.println(Arrays.asList(1, 2, 3, 4, 5).stream().collect(Collectors.maxBy(Comparator.comparingInt(o -> o))).orElse(1)); // 最小值 System.out.println(Arrays.asList(1, 2, 3, 4, 5).stream().collect(Collectors.minBy(Comparator.comparingInt(a -> a))).orElse(1)); // 统计 System.out.println(Arrays.asList(1, 2, 3, 4, 5).stream().collect(Collectors.counting())); // 求和 System.out.println(Arrays.asList(1, 2, 3, 4, 5).stream().collect(Collectors.summarizingInt(a -> a))); }
-
collectors 集合分组
/** * Stream collect 集合分组 */ private static void streamCollectGroup(){ // 集合分组 Arrays.asList(1,2,3,4,5).stream().collect(Collectors.partitioningBy(a -> a % 2 == 0)).forEach((a,b) -> System.out.println("a:"+a+",b:"+b)); Arrays.asList(1,2,3,4,5).stream().collect(Collectors.groupingBy(a -> a %2 ==0)).forEach((a,b) -> System.out.println("a:"+a+",b:"+b)); // 分组计数 Arrays.asList(1,2,3,4,5).stream().collect(Collectors.partitioningBy( a -> a % 2 == 0 ,Collectors.counting())).forEach((a,b) -> System.out.println("a:"+a+",b:"+b)); }
-
collectors.joining4
private static void streamCollectorJoining(){ // 第一个参数:分割符号 // 第二个参数:前缀符号 // 第三个参数:后缀符号 System.out.println(Arrays.asList("1", "2", "3", "4", "5").stream().collect(Collectors.joining(",", "[", "]")).toString()); }
-
Stream reduce()5
/** * Stream reduce * 1.第一个参数:起始数据 * 2.第二个参数:函数方法 */ private static void streamRuduce(){ // 字符串拼接 System.out.println(Stream.of("a", "b", "c", "d").reduce("", String::concat)); // 求最小数值 System.out.println(Stream.of(1.0, 2.0, 3.0, -1.0, -2.0).reduce(0.0, Double::min)); // 数组值求和 System.out.println(Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).reduce(0, Integer::sum)); }
private static void streamCollectorReduce(){ // 第一个参数:中间运算结果 // 第二个参数:集合中的元素 System.out.println(Arrays.asList(1, 2, 3, 4, 5).stream().reduce((a, b) -> a += b).orElse(0)); // 第一个参数:初始参数数值 // 第二个参数:中间运算结果 // 第三个参数:集合中的元素 System.out.println(Arrays.asList(1, 2, 3, 4, 5).stream().reduce(0, (a, b) -> a += b).intValue()); ArrayList<Integer> reduce = Arrays.asList(1, 2, 3, 4, 5).stream().reduce(new ArrayList<>(), (integers, integer) -> { integers.add(integer); return integers; }, (integers, integers2) -> { integers.addAll(integers2); return integers; }); System.out.println(reduce.stream().collect(Collectors.summarizingInt(a -> a))); }
private static void streamCollectorJoining(){ // 第一个参数:分割符号 // 第二个参数:前缀符号 // 第三个参数:后缀符号 System.out.println(Arrays.asList("1", "2", "3", "4", "5").stream().collect(Collectors.joining(",", "[", "]")).toString()); System.out.println(Arrays.asList("1", "2", "3", "4", "5").stream().reduce((a, b) -> a.concat(",").concat(b))); }