java8 stream和foreach哪个效率高?

Java 8引入了Stream API,提供了一种优雅和方便的方式来处理集合数据。 在Stream API中,foreach方法可以将操作作用于每个元素,而Stream中的forEach方法可以更好地处理大量的数据。

虽然,从代码实现上来看,它们的语法非常相似,但是它们背后的实现方式略有不同。Stream API是通过并行处理数据来提高效率的,而foreach则是以序列化处理方式来执行操作。 因此,在处理大量数据时,Stream比foreach更高效,因为它利用了现代多核处理器的优势。

当然,这并不意味着StreamAPI适用于所有场景。在一些小型数据集上,使用forEach可能会更加合适。同时也要注意,StreamAPI对于某些操作返回的是新的流,而非在原有流中进行修改,这也可能导致一些额外的开销。

综上所述,Stream和foreach本质上是不同的操作方式,选择哪个取决于具体的场景和数据集大小。对于大型数据集,Stream更高效。如果数据集很小,而又需要修改集合中的元素,那么使用foreach可能会更好一些。




1. 问题描述

java8 stream和foreach哪个效率高?

问题结论

150W条数据以上:stream>paralleStream>simple

150W条数据以下:simple>stream>paralleStream

从性能上考虑:小数据量用普通的forEach就可以,没有必要使用java8中的新出来的几种,已经在项目中使用的也不需要改回来,10W条也就几毫秒的差距。

2. 测试用例

import java.util.ArrayList;

import java.util.List;

public class ForEachMain {

public static void main(String[] args) {

// 实例化arrayList

List<Integer> arrayList = new ArrayList<Integer>();

int num = 15000000;

// 插入10万条数据

for (int i = 0; i < num; i++) {

arrayList.add(i);

}

List<Integer> res = new ArrayList<>();

res.clear();

// 用foreach循环arrayList

long arrayForeachStartTime = System.currentTimeMillis();

for (Integer in : arrayList) {

res.add(in);

}

long arrayForeachEndTime = System.currentTimeMillis();

System.out.println(

"用foreach循环arrayList " + (num) + "次花费时间:" + (arrayForeachEndTime - arrayForeachStartTime) + "毫秒");

res.clear();

// 用stream-foreach循环arrayList

long arrayStreamStartTime = System.currentTimeMillis();

arrayList.stream().forEach(e -> res.add(e));

long arrayStreamEndTime = System.currentTimeMillis();

System.out.println(

"用Stream-foreach循环arrayList " + (num) + "次花费时间:" + (arrayStreamEndTime - arrayStreamStartTime) + "毫秒");

res.clear();

// 用parallelStream-foreach循环arrayList

long arrayParallelStreamStartTime = System.currentTimeMillis();

arrayList.parallelStream().forEach(e -> res.add(e));

long arrayParallelStreamEndTime = System.currentTimeMillis();

System.out.println("用parallelStream-foreach循环arrayList " + (num) + "万次花费时间:"

+ (arrayParallelStreamEndTime - arrayParallelStreamStartTime) + "毫秒");

}

}

2.1 当num = 50000000时

用foreach循环arrayList 5000万次花费时间:2840毫秒

用stream-foreach循环arrayList 5000万次花费时间:507毫秒

用parallelStream-foreach循环arrayList 5000万次花费时间:1168毫秒

2.2 当num = 500000时

用foreach循环arrayList 50万次花费时间:13毫秒

用stream-foreach循环arrayList 50万次花费时间:25毫秒

用parallelStream-foreach循环arrayList 50万次花费时间:35毫秒

2.3 当num = 5000时

用foreach循环arrayList 5000次花费时间:1毫秒

用stream-foreach循环arrayList 0万次花费时间:16毫秒

用parallelStream-foreach循环arrayList 0万次花费时间:8毫秒

最直观的感觉,stream的流式处理应该比较快,这种想当然的推测,需要事实去佐证,运行过测试代码之后,发现并不是那么回事。耳听为虚,眼见为实,李子是不是涩的,最简单的方式是尝一口。请记住,编写代码时,一定要以最简洁为原则,毕竟运行程序的硬件成本会随着时间的推移在不断降低。

作者:夕阳雨晴,欢迎关注我的头条号:偶尔美文,主流Java,为你讲述不一样的码农生活。




java8 stream和foreach哪个效率高?

很明显java8 stream效率高!

为什么这么说?

java8 stream是基于Lambda表达式函数式流的编程

Java 程序员在使用集合类时,一个通用的模式是在集合上进行迭代,然后处理返回的每一 个元素


使用类库后的方法调用流程


Stream 是用函数式编程方式在集合类上进行复杂操作的工具。

常用的流函数操作

1,collect(toList())

collect(toList()) 方法由 Stream 里的值生成一个列表,是一个及早求值操作


List collected = Stream.of("a", "b", "hello") .map(string -> string.toUpperCase()) n .collect(toList()); assertEquals(asList("A", "B", "HELLO"), collected);

传给 map ➊ 的 Lambda 表达式只接受一个 String 类型的参数,返回一个新的 String。

参数 和返回值不必属于同一种类型,但是 Lambda 表达式必须是 Function 接口的一个实例(如 图所示),Function 接口是只包含一个参数的普通函数接口


2,filter

遍历数据并检查其中的元素时,可尝试使用 Stream 中提供的新方法 filter

和 map 很像,filter 接受一个函数作为参数,该函数用 Lambda 表达式表示。该函数和前面 示例中 if 条件判断语句的功能一样,如果字符串首字母为数字,则返回 true。若要重构 遗留代码,for 循环中的 if 条件语句就是一个很强的信号,可用 filter 方法替代。 由于此方法和 if 条件语句的功能相同,因此其返回值肯定是 true 或者 false。经过过滤, Stream 中符合条件的,即 Lambda 表达式值为 true 的元素被保留下来。该 Lambda 表达式 的函数接口正Predicate


3,flatMap

flatMap 方法可用 Stream 替换值,然后将多个 Stream 连接成一个 Stream


它可以用一个新的值代替 Stream 中的值。但有时,用户希望让 map 操作有点变化,生成一个新的 Stream 对象取而代之。用户通常不希望结果是一连串的流失, 此时 flatMap 最能派上用场

包含多个列表的

Stream List together = Stream.of(asList(1, 2), asList(3, 4)) .flatMap(numbers -> numbers.stream()) .collect(toList());


4,reduce

Stream 的求和结果,每一步都将 Stream 中的元素累加至 accumulator,遍历至 Stream 中的 最后一个元素时,accumulator 的值就是所有元素的和


我们可以对比两个代码

List musicians = album.getMusicians() .collect(toList());

List bands = musicians.stream() .filter(artist -> artist.getName().startsWith("The")) .collect(toList()); Set origins = bands.stream() .map(artist -> artist.getNationality()) .collect(toSet());

//下面是通过链式调用

Set origins = album.getMusicians()

.filter(artist -> artist.getName().startsWith("The"))

.map(artist -> artist.getNationality())

.collect(toSet())

  • 代码可读性差,样板代码太多,隐藏了真正的业务逻辑;
  • 效率差,每一步都要对流及早求值,生成新的集合;
  • 代码充斥一堆垃圾变量,它们只用来保存中间结果,除此之外毫无用处;
  • 难于自动并行化处理。 当然,刚开始写基于流程的程序时,这样的情况在所难免。

但是如果发现自己经常写出这样 的代码,就要反思能否将代码重构得更加简洁易读。

java8的函数好处是:

Stream使用习惯的链式调用 通过高阶函数重构遗留程序代码,提高程序执行性能。

小杨互联网bug的行走者,关注我让你了解更多的知识!




使用for循环,串行Stream流,并行Stream流来对5亿个数字求和。看消耗的时间。

public class Demo06 {
private static long times = 50000000000L;
private long start;

@Before
public void init() {
start = System.currentTimeMillis();
}

@After
public void destory() {
long end = System.currentTimeMillis();
System.out.println("消耗时间: " + (end - start));

}

// 测试效率,parallelStream 120
@Test
public void parallelStream() {
System.out.println("serialStream");
LongStream.rangeClosed(0, times)
.parallel()
.reduce(0, Long::sum);
}

// 测试效率,普通Stream 342
@Test
public void serialStream() {
System.out.println("serialStream");
LongStream.rangeClosed(0, times)
.reduce(0, Long::sum);
}

// 测试效率,正常for循环 421
@Test
public void forAdd() {
System.out.println("forAdd");
long result = 0L;
for (long i = 1L; i < times; i++) {
result += i;
}
}
}

我们可以看到parallelStream的效率是最高的。

Stream并行处理的过程会分而治之,也就是将一个大任务切分成多个小任务,这表示每个任务都是一个操作。




在Java 8中,Stream和foreach都是用于遍历集合或数组的方式,但它们的实现和使用场景略有不同。

Stream是Java 8引入的功能强大的流式处理API,它提供了丰富的操作方法来对集合进行处理和转换。使用Stream可以通过链式调用多个操作方法来完成对集合的处理,例如过滤、映射、排序等。Stream采用了惰性求值的机制,可以充分利用并行处理提高性能。

而foreach是Iterable接口的默认方法,用于对集合或数组进行遍历操作。它是一种简单直接的遍历方式,逐个处理集合中的元素。foreach的实现是顺序执行的,不能直接支持并行处理。

从效率上来说,如果只是遍历集合并执行简单的操作,foreach可能会稍微高效一些,因为它没有引入Stream的额外开销和复杂性。但如果需要进行更复杂的集合处理,例如筛选、映射、聚合等操作,Stream的性能会更好。Stream利用了惰性求值和并行处理的特性,可以更好地利用多核处理器和优化算法,从而提高整体的执行效率。

综上所述,如果只需要简单地遍历集合,foreach可能更适合;如果需要进行复杂的集合处理,特别是在大数据集上,Stream可能更高效。然而,具体的性能差异还取决于具体的使用场景和操作,因此在选择使用Stream还是foreach时,建议根据实际需求进行评估和测试。

展开阅读全文

页面更新:2024-05-20

标签:多核   链式   遍历   高效   表达式   函数   元素   效率   代码   操作   方式   时间   测试   方法   数据   财经

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top