热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java8Stream流Intermediate中间操作详细解析

Stream的操作中有中间操作和终端操作,顾名思义,中间操作就是对stream流的一些操作,操作对象时stream本身,终端操作既是对流的处理结

Stream的操作中有中间操作和终端操作,顾名思义,中间操作就是对stream流的一些操作,操作对象时stream本身,终端操作既是对流的处理结果,为了直观的了解,我们看下接口定义:

public interface Stream<T> extends BaseStream<T, Stream<T>> {Stream<T> filter(Predicate<? super T> predicate);<R> Stream<R> map(Function<? super T, ? extends R> mapper);IntStream mapToInt(ToIntFunction<? super T> mapper);LongStream mapToLong(ToLongFunction<? super T> mapper);DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper);LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper);DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper);Stream<T> distinct();Stream<T> sorted();Stream<T> sorted(Comparator<? super T> comparator);Stream<T> peek(Consumer<? super T> action);Stream<T> limit(long maxSize);Stream<T> skip(long n);void forEach(Consumer<? super T> action);void forEachOrdered(Consumer<? super T> action);Object[] toArray();<A> A[] toArray(IntFunction<A[]> generator);T reduce(T identity, BinaryOperator<T> accumulator);Optional<T> reduce(BinaryOperator<T> accumulator);<U> U reduce(U identity,BiFunction<U, ? super T, U>accumulator,
BinaryOperator<U> combiner);<R> R collect(Supplier<R> supplier,iConsumer<R, ? super T> accumulator,iConsumer<R, R> combiner);<R, A> R collect(Collector<? super T, A, R> collector);Optional<T> min(Comparator<? super T> comparator);Optional<T> max(Comparator<? super T> comparator);long count();boolean anyMatch(Predicate<? super T> predicate);boolean allMatch(Predicate<? super T> predicate);boolean noneMatch(Predicate<? super T> predicate);Optional<T> findFirst();Optional<T> findAny();public static<T> Builder<T> builder() {return new Streams.StreamBuilderImpl<>();}public static<T> Stream<T> empty() {return StreamSupport.stream(Spliterators.<T>emptySpliterator(), false);}public static<T> Stream<T> of(T t) {return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);}public static<T> Stream<T> of(T... values) {return Arrays.stream(values);}
}

对于返回值为** 接口本身的Stream ** 或者返回 其他对象类型的&#xff0c;返回接口类型的我们都可认为是中间操作&#xff0c;返回 其他具体类型的为终端操作。
下面我们来具体看每个方法&#xff1a;
1、filter(Predicate) 将结果为false的元素过滤掉

&#64;Test
public void testFilter(){Stream<Integer> stream &#61; Stream.of(1, 2, 3);stream.filter(e->e > 2).forEach(System.out::println);// 符合大于2的数字 -> 3
}

filter() 传入需要过滤的条件
2、map(fun) 转换元素的值&#xff0c;可以用方法引元或者lambda表达式

&#64;Test
public void testMap(){Stream<Integer> stream &#61; Stream.of(1, 2, 3);stream.map(o -> Integer.toString(o)).forEach(s->{System.out.println(s);// 1,2,3System.out.println(s.getClass());// class java.lang.String});List<Dish> dishes &#61; Arrays.asList(new Dish("beef", "100", 200, Dish.Type.MEAT),new Dish("pork", "false", 800, Dish.Type.MEAT),new Dish("rice", "true", 350, Dish.Type.OTHER));dishes.stream().map(Dish::getName).forEach(System.out::println);// beef pork rice
}

可以看到&#xff0c;使用map方法实现了Integer-> String的类型转换&#xff0c;也可以获取对象的某一属性值等等。
3、flatMap(fun) 若元素是流&#xff0c;将流摊平为正常元素&#xff0c;再进行元素转换

String [] arr &#61; {"aaa","bbb","ccc"};
Arrays.stream(arr).map(s-> s.split("")).forEach(System.out::println);// [Ljava.lang.String;&#64;33e5ccce
List<String[]> collect &#61; Arrays.stream(arr).map(s -> s.split("")).collect(Collectors.toList());

我们可以看到使用map时输出的是一个地址&#xff0c;返回的类型实际是 List 使用flatMap时

List<String> list &#61; Arrays.stream(arr).map(s -> s.split("")).flatMap(Arrays::stream).collect(Collectors.toList());
Arrays.stream(arr).map(s->s.split("")).flatMap(Arrays::stream).forEach(System.out::println);// aaabbbccc

可以看到返回的类型为List &#xff0c;将整个外层list包含的所有元素放到一个层面处理。
4、limit(n) 保留前n个元素

List<Dish> mean &#61; Arrays.asList(new Dish("pork", "false", 800, Dish.Type.MEAT),new Dish("beef", "false", 700, Dish.Type.MEAT),new Dish("chicken", "false", 400, Dish.Type.MEAT),new Dish("french fries", "true", 530, Dish.Type.OTHER),new Dish("rice", "true", 350, Dish.Type.OTHER),new Dish("season fruit", "true", 120, Dish.Type.OTHER),new Dish("pizza", "true", 550, Dish.Type.OTHER),new Dish("prawns", "false", 300, Dish.Type.FISH),new Dish("salmon", "false", 450, Dish.Type.FISH)
);
//截取前2个菜品
List<Dish> dishes &#61; mean.stream().limit(2).collect(Collectors.toList());
System.out.println(dishes.size());//2
mean.stream().limit(2).forEach(System.out::println);
//Dish{name&#61;&#39;pork&#39;, vegetarian&#61;&#39;false&#39;, calories&#61;800, type&#61;MEAT}
//Dish{name&#61;&#39;beef&#39;, vegetarian&#61;&#39;false&#39;, calories&#61;700, type&#61;MEAT}

5、skip(n) 跳过前n个元素

// 跳过前7个菜品
mean.stream().skip(7).forEach(System.out::println);
//Dish{name&#61;&#39;prawns&#39;, vegetarian&#61;&#39;false&#39;, calories&#61;300, type&#61;FISH}
//Dish{name&#61;&#39;salmon&#39;, vegetarian&#61;&#39;false&#39;, calories&#61;450, type&#61;FISH}

对于limit 和 skip 配合使用可以实现分页操作
**6、distinct() 去重 剔除重复元素 **

&#64;Test
public void testDistinct(){int[] arr &#61; {1,1,2,2,3,4,5};Arrays.stream(arr).distinct().forEach(System.out::println);// 1 2 3 4 5
}

7、sorted() 排序 默认升序

int[] arr &#61; {5,7,3,1,8,4};
Arrays.stream(arr).sorted().forEach(System.out::println);// 134578

8、sorted(Comparator) 按传入的条件排序

List<Dish> mean &#61; Arrays.asList(new Dish("pork", "false", 800, Dish.Type.MEAT),new Dish("beef", "false", 700, Dish.Type.MEAT),new Dish("chicken", "false", 400, Dish.Type.MEAT),new Dish("french fries", "true", 530, Dish.Type.OTHER),new Dish("rice", "true", 350, Dish.Type.OTHER),new Dish("season fruit", "true", 120, Dish.Type.OTHER),new Dish("pizza", "true", 550, Dish.Type.OTHER),new Dish("prawns", "false", 300, Dish.Type.FISH),new Dish("salmon", "false", 450, Dish.Type.FISH)
);
// 按菜品的卡路里排序 并打印卡路里的值
mean.stream().sorted(Comparator.comparing(Dish::getCalories)).map(Dish::getCalories).forEach(System.out::println);//120 300 350 400 450 530 550 700 800
// reversed 反转 实现倒叙排序
mean.stream().sorted(Comparator.comparing(Dish::getCalories).reversed()).map(Dish::getCalories).forEach(System.out::println);// 800 700 550 530 450 400 350 300 120

9、peek(fun) 流不变 接收一个没有返回值的λ表达式&#xff0c;可以做一些输出&#xff0c;外部处理

&#64;Test
public void testPeek(){int [] arr &#61; {1,1,2,3,4,4,5};Arrays.stream(arr).distinct().map(o-> o*2).peek(s->System.out.println("peek 做一些输出操作"&#43;s)).forEach(System.out::println);
}

peek 和 map 的区别
peek 的定义

Stream<T> peek(Consumer<? super T> action);

熟悉lambda的都知道Consumer的实现类 应该只有一个方法&#xff0c;该方法返回类型为void。

Consumer<Integer> c &#61; i -> System.out.println("hello" &#43; i);

map的定义

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

我们发现Function 比 Consumer 多了一个 return。 map接收一个有返回值的lambda表达式&#xff0c;之后Stream的泛型类型将转换为map参数λ表达式返回的类型

Function<Integer,String> f &#61; x -> {return "hello" &#43; i;};


推荐阅读
  • 本文将详细探讨 Java 中提供的不可变集合(如 `Collections.unmodifiableXXX`)和同步集合(如 `Collections.synchronizedXXX`)的实现原理及使用方法,帮助开发者更好地理解和应用这些工具。 ... [详细]
  • 本文详细探讨了Java中的ClassLoader类加载器的工作原理,包括其如何将class文件加载至JVM中,以及JVM启动时的动态加载策略。文章还介绍了JVM内置的三种类加载器及其工作方式,并解释了类加载器的继承关系和双亲委托机制。 ... [详细]
  • Java 架构:深入理解 JDK 动态代理机制
    代理模式是 Java 中常用的设计模式之一,其核心在于代理类与委托类共享相同的接口。代理类主要用于为委托类提供预处理、过滤、转发及后处理等功能,以增强或改变原有功能的行为。 ... [详细]
  • 本文介绍如何使用 Android 的 Canvas 和 View 组件创建一个简单的绘图板应用程序,支持触摸绘画和保存图片功能。 ... [详细]
  • 深入解析Java枚举及其高级特性
    本文详细介绍了Java枚举的概念、语法、使用规则和应用场景,并探讨了其在实际编程中的高级应用。所有相关内容已收录于GitHub仓库[JavaLearningmanual](https://github.com/Ziphtracks/JavaLearningmanual),欢迎Star并持续关注。 ... [详细]
  • 实用正则表达式有哪些
    小编给大家分享一下实用正则表达式有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下 ... [详细]
  • 本文介绍如何从字符串中移除大写、小写、特殊、数字和非数字字符,并提供了多种编程语言的实现示例。 ... [详细]
  • 深入解析SpringMVC核心组件:DispatcherServlet的工作原理
    本文详细探讨了SpringMVC的核心组件——DispatcherServlet的运作机制,旨在帮助有一定Java和Spring基础的开发人员理解HTTP请求是如何被映射到Controller并执行的。文章将解答以下问题:1. HTTP请求如何映射到Controller;2. Controller是如何被执行的。 ... [详细]
  • This post discusses an issue encountered while using the @name annotation in documentation generation, specifically regarding nested class processing and unexpected output. ... [详细]
  • 优化JavaScript中的多条件判断逻辑
    本文探讨了在JavaScript中遇到复杂逻辑判断时,如何通过不同的方法优化if/else或switch语句,以提高代码的可读性和可维护性。 ... [详细]
  • 深入解析Spring启动过程
    本文详细介绍了Spring框架的启动流程,帮助开发者理解其内部机制。通过具体示例和代码片段,解释了Bean定义、工厂类、读取器以及条件评估等关键概念,使读者能够更全面地掌握Spring的初始化过程。 ... [详细]
  • 深入解析动态代理模式:23种设计模式之三
    在设计模式中,动态代理模式是应用最为广泛的一种代理模式。它允许我们在运行时动态创建代理对象,并在调用方法时进行增强处理。本文将详细介绍动态代理的实现机制及其应用场景。 ... [详细]
  • 在编译BSP包过程中,遇到了一个与 'gets' 函数相关的编译错误。该问题通常发生在较新的编译环境中,由于 'gets' 函数已被弃用并视为安全漏洞。本文将详细介绍如何通过修改源代码和配置文件来解决这一问题。 ... [详细]
  • 2017-2018年度《网络编程与安全》第五次实验报告
    本报告详细记录了2017-2018学年《网络编程与安全》课程第五次实验的具体内容、实验过程、遇到的问题及解决方案。 ... [详细]
  • 本文档提供了如何使用C#代码从客户订单中提取产品信息的方法,适用于需要处理和分析产品数据的应用场景。 ... [详细]
author-avatar
思念如此难受_351
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有