关于stream:还在stream中使用peek不要被这些陷阱绊住了

简介自从JDK中引入了stream之后,好像所有都变得很简略,依据stream提供的各种办法,如map,peek,flatmap等等,让咱们的编程变得更美妙。 事实上,我也常常在我的项目中看到有些小伙伴会常常应用peek来进行一些业务逻辑解决。 那么既然JDK文档中说peek办法次要是在调试的状况下应用,那么peek肯定存在着某些鲜为人知的毛病。一起来看看吧。 peek的定义和根本应用先来看看peek的定义: Stream<T> peek(Consumer<? super T> action);peek办法承受一个Consumer参数,返回一个Stream后果。 而Consumer是一个FunctionalInterface,它须要实现的办法是上面这个: void accept(T t);accept对传入的参数T进行解决,然而并不返回任何后果。 咱们先来看下peek的根本应用: public static void peekOne(){ Stream.of(1, 2, 3) .peek(e -> log.info(String.valueOf(e))) .toList(); }运行下面的代码,咱们能够失去: [main] INFO com.flydean.Main - 1[main] INFO com.flydean.Main - 2[main] INFO com.flydean.Main - 3逻辑很简略,就是打印出Stream中的元素而已。 peek的流式解决peek作为stream的一个办法,当然是流式解决的。接下来咱们用一个具体的例子来阐明流式解决具体是如何操作的。 public static void peekForEach(){ Stream.of(1, 2, 3) .peek(e -> log.info(String.valueOf(e))) .forEach(e->log.info("forEach"+e)); }这一次咱们把toList办法替换成了forEach,通过具体的打印日志来看看到底产生了什么。 [main] INFO com.flydean.Main - 1[main] INFO com.flydean.Main - forEach1[main] INFO com.flydean.Main - 2[main] INFO com.flydean.Main - forEach2[main] INFO com.flydean.Main - 3[main] INFO com.flydean.Main - forEach3通过日志,咱们能够看出,流式解决的流程是对应流中的每一个元素,别离经验了peek和forEach操作。而不是先把所有的元素都peek过后再进行forEach。 ...

March 21, 2023 · 2 min · jiezi

关于stream:简单聊聊Streamreduce用法解析

根本应用先举一个简略的例子: 算法题:Words题目形容每个句子由多个单词组成,句子中的每个单词的长度都可能不一样,咱们假如每个单词的长度Ni为该单词的分量,你须要做的就是给出整个句子的均匀分量V。 解答要求工夫限度:1000ms, 内存限度:100MB输出输出只有一行,蕴含一个字符串S(长度不会超过100),代表整个句子,句子中只蕴含大小写的英文字母,每个单词之间有一个空格。 输入输入句子S的均匀分量V(四舍五入保留两位小数)。 Who Love Solo输入样例3.67 这道题的意思是求一句话中每个单词的均匀长度,咱们求得总长度而后除以单词数量即可,刚好能用到reduce()这个办法。 public class Demo {public static void main(String[] args) {Scanner sc = new Scanner(System.in);String[] s = sc.nextLine().split(" ");double res = Arrays.stream(s).mapToDouble(a ->a.length()).reduce(0,(a,b)->a+b);System.out.println(String.format("%.2f",res/s.length));}} 在代码中,.reduce(0,(a,b)->a+b);这一块就是咱们经典的应用案例,咱们要先明确其中a,b的含意,而后再学习如何应用要害概念:初始值的定义(Identity),累加器(Accumulator),组合器(Combiner) Identity : 定义一个元素代表是归并操作的初始值,如果Stream 是空的,也是Stream 的默认后果Accumulator: 定义一个带两个参数的函数,第一个参数是上个归并函数的返回值,第二个是Strem 中下一个元素。Combiner: 调用一个函数来组合归并操作的后果,当归并是并行执行或者当累加器的函数和累加器的实现类型不匹配时才会调用此函数。也就是说0就是咱们的初始值,(a,b)->a+b就是咱们的累加器,其中a就是上一次的计算结果,b就是Stream流中以后元素,而前面的a+b则是计算规定,比方如果咱们改成a*b,那就是计算乘积了,当然咱们也能够用办法援用来代替 lambda 表达式。 double res = Arrays.stream(s).mapToDouble(a ->a.length()).reduce(0,Double::sum);1这就是最根本的应用了,不晓得小伙伴们有没有学会呢? 额定举例 当然,咱们能够用reduce 办法解决其余类型的 stream,例如,能够操作一个 String 类型的数组,把数组的字符串进行拼接。 List<String> letters = Arrays.asList("a", "b", "c", "d", "e");String result = letters.stream().reduce("", (partialString, element) -> partialString + element);assertThat(result).isEqualTo("abcde"); ...

January 3, 2023 · 1 min · jiezi

关于stream:Java18-Stream流的使用

流的应用无状态:解决单个数据有状态:解决所有数据两头操作(无状态)两头操作(有状态)终端操作(短路)终端操作(非短路)过滤(filter)去重(distinct)所有匹配(allMatch)遍历(forEach)映射(map)跳过(skip)任意匹配(anyMatch)归约(reduce)扁平化(flatMap)截断(limit)不匹配(noneMatch)最大值(max)遍历(peek)排序(sorted)查找首个(findFirst)最小值(min) 查找任意(findAny)聚合(collect) 计数(count)

November 20, 2022 · 1 min · jiezi

关于stream:Java-Stream

流操作分类两头操作无状态操作【对单个数据进行解决】filtermappeek有状态操作【对所有的数据进行解决】dictinctsorted limit终端操作非短路操作forEachcollectcount短路操作anyMatchfindFirstfindAll两头操作(无状态)两头操作(有状态)终端操作(短路)终端操作(非短路)过滤(filter)去重(distinct)所有匹配(allMatch)遍历(forEach)映射(map)跳过(skip)任意匹配(anyMatch)归约(reduce)扁平化(flatMap)截断(limit)不匹配(noneMatch)最大值(max)遍历(peek)排序(sorted)查找首个(findFirst)聚合(collect) 查找任意(findAny)最小值(min) 计数(count)

November 20, 2022 · 1 min · jiezi

关于stream:stream使用

一:stream应用范畴:对数组、Collection等汇合类中的元素进行操作(数组、List、Set、Map)二:流操作的步骤 1、创立stream API阐明stream创立出一个新的stream串行流对象parallelStream()创立出一个可并行执行的stream流对象Stream.of()通过给定的一系列元素创立一个新的Stream串行流对象2、stream两头解决 3、终止stream![image.png](/img/bVc2ZEh)三:流的应用https://www.cnblogs.com/softw...

October 13, 2022 · 1 min · jiezi

关于stream:JDK8-Stream性能测试看看到底有多快

送大家以下学习材料,文末有支付形式 JDK8 Stream 数据流效率剖析Stream 是Java SE 8类库中新增的要害形象,它被定义于 java.util.stream (这个包里有若干流类型:Stream<T> 代表对象援用流。 此外还有一系列特化流,如 IntStream,LongStream,DoubleStream等 ),Java 8 引入的的Stream次要用于取代局部Collection的操作,每个流代表一个值序列,流提供一系列罕用的汇集操作,能够便捷的在它下面进行各种运算。 汇合类库也提供了便捷的形式使咱们能够以操作流的形式应用汇合、数组以及其它数据结构; stream 的操作品种 ①两头操作 当数据源中的数据上了流水线后,这个过程对数据进行的所有操作都称为“两头操作”;两头操作依然会返回一个流对象,因而多个两头操作能够串连起来造成一个流水线;stream 提供了多种类型的两头操作,如 filter、distinct、map、sorted 等等;②终端操作 当所有的两头操作实现后,若要将数据从流水线上拿下来,则须要执行终端操作;stream 对于终端操作,能够间接提供一个两头操作的后果,或者将后果转换为特定的 collection、array、String 等;stream 的特点①只能遍历一次: 数据流的从一头获取数据源,在流水线上顺次对元素进行操作,当元素通过流水线,便无奈再对其进行操作,能够从新在数据源获取一个新的数据流进行操作; ②采纳外部迭代的形式: 对Collection进行解决,个别会应用 Iterator 遍历器的遍历形式,这是一种内部迭代; 而对于解决Stream,只有申明解决形式,处理过程由流对象自行实现,这是一种外部迭代,对于大量数据的迭代解决中,外部迭代比内部迭代要更加高效; stream 绝对于 Collection 的长处无存储:流并不存储值;流的元素源自数据源(可能是某个数据结构、生成函数或I/O通道等等),通过一系列计算步骤失去;函数式格调:对流的操作会产生一个后果,但流的数据源不会被批改;惰性求值:少数流操作(包含过滤、映射、排序以及去重)都能够以惰性形式实现。这使得咱们能够用一遍遍历实现整个流水线操作,并能够用短路操作提供更高效的实现;无需上界:不少问题都能够被表白为有限流(infinite stream):用户不停地读取流直到称心的后果呈现为止(比如说,枚举 完满数 这个操作能够被表白为在所有整数上进行过滤);汇合是无限的,但流能够表白为无线流;代码简练:对于一些collection的迭代解决操作,应用 stream 编写能够非常简洁,如果应用传统的 collection 迭代操作,代码可能非常啰嗦,可读性也会比拟蹩脚;stream 和 iterator 迭代的效率比拟好了,下面 stream 的长处吹了那么多,stream 函数式的写法是很难受,那么 steam 的效率到底怎么呢? 先说论断: - 传统 iterator (for-loop) 比 stream(JDK8) 迭代性能要高,尤其在小数据量的状况下; - 在多核情景下,对于大数据量的解决,parallel stream 能够有比 iterator 更高的迭代解决效率; 我别离对一个随机数列 List (数量从 10 到 10000000)进行映射、过滤、排序、规约统计、字符串转化场景下,对应用 stream 和 iterator 实现的运行效率进行了统计,。 ...

June 3, 2021 · 1 min · jiezi

关于stream:Java8-Stream-提高编码效率早点下班

编程中操作汇合数据是十分频繁的,应用Java8 中的Stream对汇合解决,联合Lambda函数式编程能极大的简化代码,正当的应用Stream能进步代码可读性,另一方面从Java8面世以来Stream API通过了有数我的项目的实际考验,其稳定性和性能自不必说,网上有很多相干的性能测试案例能够查阅参考,如果有人对你说:Lambda 可读性不好,保护老本低等一些问题,你大可释怀,请肯定看下最初的留神点 1. Stream 创立Stream的创立形式比拟多,接下来介绍几种罕用的形式,以下Lists应用的google guava的API,间接上代码: // 形式1:Stream.of以及其余的静态方法,测试常应用Stream<String> stream1 = Stream.of("A", "B");// 形式2:Collection形式,常见如(List、Set)Stream<String> stream2 = Lists.newArrayList("A", "B").stream();Stream<String> stream3 = Sets.newHashSet("A", "B").stream();// 形式3:数组形式Stream<String> stream4 = Arrays.stream(new String[]{"A", "B"});// 形式4:通过API接口创立,文件API等Stream<String> stream5 = Files.lines(Paths.get("/file.text"));// 形式5:创立根本数据类型对应的Stream,如:IntStream、LongStream、DoubleStreamIntStream stream6 = Arrays.stream(new int[] { 1, 2, 3 });// 形式6:通过Stream.builder创立Stream<Object> stream7 = Stream.builder().add("A").build();以上创立形式形式2、形式3比拟罕用,其中形式3也能够应用parallelStream创立并行流,其余的形式能够通过parallel办法转换为并行流,在数据量较大时进步数据处理效率,如下: // 间接应用parallelStream创立Stream<String> stream1 = Lists.newArrayList("A", "B").parallelStream();// 应用parallel转化一般流为并行流Stream<String> stream2 = Arrays.stream(new String[]{"A", "B"}).parallel();2. Stream 两头操作Stream.map将原数据处理后生成新的数据,其中mapToInt、mapToLong、mapToDouble办法可间接转换为IntStream、LongStream、DoubleStream(用的比拟少,大家可自行查找) // 原数据增加后缀-NList<String> result1 = Lists.newArrayList("A") .stream().map(item -> item + "-N").collect(Collectors.toList());// 原字符串转化为数组List<String[]> result2 = Lists.newArrayList("A") .stream().map(item -> new String[]{item}).collect(Collectors.toList());Stream.flatMap合并多个Stream为一个Stream,常常用在合并多个List数据 ...

May 16, 2021 · 2 min · jiezi

关于java8:java8-stream处理集合

list分组后统计 List<UserInfo> userList = Lists.newArrayList(); Map<String, Long> collect = userList.stream() .collect(Collectors.groupingBy(UserInfo::getId, Collectors.counting()));待更新 待更新

April 14, 2021 · 1 min · jiezi