热门标签 | 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;};


推荐阅读
  • 本文介绍了在实现了System.Collections.Generic.IDictionary接口的泛型字典类中如何使用foreach循环来枚举字典中的键值对。同时还讨论了非泛型字典类和泛型字典类在foreach循环中使用的不同类型,以及使用KeyValuePair类型在foreach循环中枚举泛型字典类的优势。阅读本文可以帮助您更好地理解泛型字典类的使用和性能优化。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 也就是|小窗_卷积的特征提取与参数计算
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了卷积的特征提取与参数计算相关的知识,希望对你有一定的参考价值。Dense和Conv2D根本区别在于,Den ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 第四章高阶函数(参数传递、高阶函数、lambda表达式)(python进阶)的讲解和应用
    本文主要讲解了第四章高阶函数(参数传递、高阶函数、lambda表达式)的相关知识,包括函数参数传递机制和赋值机制、引用传递的概念和应用、默认参数的定义和使用等内容。同时介绍了高阶函数和lambda表达式的概念,并给出了一些实例代码进行演示。对于想要进一步提升python编程能力的读者来说,本文将是一个不错的学习资料。 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
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社区 版权所有