`
crazy.j
  • 浏览: 5098 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

了解Java8 Stream。

 
阅读更多

JDK8不久前正式发布了,这一次更新为我们带来了相当多的东西,其中一个非常庞大也是非常复杂的框架Stream,特别值得一提,他可以将一些让人烦躁的事情变得简洁,好,进入正题。

 

现在需要除去一个无序数组中大于800的数

 

传统方法:

		for(int i = 0; i < list.size(); i++) {
			if(list.get(i) > 800) {
				list.remove(i);
			}
		}

 使用Stream与lambda

list.stream().filter((n) -> n <= 800);

 

如此痛快已经显而易见了,但对于没有了解lambda表达式的童鞋们对类似代码有些抵触,接下来我们还使用传统的Java代码介绍几个比较常用的API。

	public static void learnMore(List<Integer> list) {
		// 创建流式调用对象
		list.stream()
		
		// 过滤,只保留值大于800的元素。
		.filter(new Predicate<Integer>() {

			@Override
			public boolean test(Integer t) {
				return t > 800;
			}
			
		})
		
		// 排序,默认升序,可传入Comparator。
		.sorted()
		
		// 通过map方法将集合中的对象转换为String类型
		.map(new Function<Integer, String>() {
			@Override
			public String apply(Integer t) {
				return new StringBuilder("String[").append(t).append("]").toString();
			}
		})
		
		// 获取集合中最多n个元素。
		.limit(10)
		
		.forEach(new Consumer<String>() {
			@Override
			public void accept(String t) {
				System.out.println(t);
			}
		});
		
		System.out.println("List size:" + list.size());
	}

 程序输出:

String[801]

String[802]

String[803]

String[804]

String[805]

String[806]

String[807]

String[808]

String[809]

String[810]

List size:1000

通过输出我们可以看到整个流程中所有的操作得到了处理,且所有操作均没有涉及对原集合的变动,探查源代码发现stream对象是靠原集合创建迭代器进行所有操作,因此不对原集合内容进行改动。

 

接下来我们看一个比较有意思的事情:

	public static void whyNoPrint(List<Integer> list) {
		list.stream()
		
		.filter(new Predicate<Integer>() {

			@Override
			public boolean test(Integer t) {
				System.out.println(t);
				return true;
			}
		});
	}

该方法执行过后程序没有任何输出,其实本人最初并不知道这个细节,而是在研究另外一个事情的时候发现的,稍微想一想就能看出这个程序有问题,流对象在filter后就不做任何事情了,所以这个筛选操作也失去了意义,应该是JDK在设计时考虑到的细节,非常值得我们学习。

 

接下来的东西实在是让人太兴奋了:并行流

这个东西是在研究stream.reduce方法时候发现的,reduce提供三个方法的重载,分别为1个参数,两个参数与三个参数,在尝试使用三个参数的reduce方法时候我发现了一个问题,就是最后一个参数传入的BinaryOperator.apply方法根本没有被调用!通过一番苦苦的读源代码工作后我发现reduce方法的第三个参数仅仅在stream以并行模式工作时才会生效!为什么?他是做什么的?我们来看下面的代码:

	public static void learnReduce_3(List<Integer> list) {
		// 并行流
		Stream<Integer> parallelStream = list.stream().parallel();
		// 串行流
		Stream<Integer> sequentialStream = list.stream();
		
		long start = System.currentTimeMillis();
		parallelStream.reduce(0, new BiFunction<Integer, Integer, Integer>() {

			@Override
			public Integer apply(Integer t, Integer u) {
				// 在这里停顿10毫秒来提高并行与串行计算的差异。
				// 虽然流提供了并行计算支持,但如果你需要处理的问题非常简单,还是推荐使用串行模式。
				// 因为那样避免了并行计算自身的开销,会更快。
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
				}
				return t + u;
			}
		}, new BinaryOperator<Integer>() {

			@Override
			public Integer apply(Integer left, Integer right) {
				System.out.println(Thread.currentThread().getName());
				return left + right;
			}
		});
		System.out.println("Parallel stream processed with " + (System.currentTimeMillis() - start) + "ms.");
		
		start = System.currentTimeMillis();
		sequentialStream.reduce(0, new BiFunction<Integer, Integer, Integer>() {

			@Override
			public Integer apply(Integer t, Integer u) {
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
				}
				return t + u;
			}
		}, new BinaryOperator<Integer>() {

			@Override
			public Integer apply(Integer t, Integer u) {
				System.out.println("Can't print this line.");
				return 0;
			}
		});
		System.out.println("Sequential stream processed with " + (System.currentTimeMillis() - start) + "ms.");
	}

 程序输出:

ForkJoinPool.commonPool-worker-3

ForkJoinPool.commonPool-worker-7

ForkJoinPool.commonPool-worker-2

main

ForkJoinPool.commonPool-worker-6

ForkJoinPool.commonPool-worker-4

ForkJoinPool.commonPool-worker-1

ForkJoinPool.commonPool-worker-1

ForkJoinPool.commonPool-worker-5

ForkJoinPool.commonPool-worker-3

ForkJoinPool.commonPool-worker-3

ForkJoinPool.commonPool-worker-7

ForkJoinPool.commonPool-worker-7

ForkJoinPool.commonPool-worker-2

ForkJoinPool.commonPool-worker-2

ForkJoinPool.commonPool-worker-2

ForkJoinPool.commonPool-worker-5

ForkJoinPool.commonPool-worker-5

ForkJoinPool.commonPool-worker-5

ForkJoinPool.commonPool-worker-5

ForkJoinPool.commonPool-worker-4

ForkJoinPool.commonPool-worker-4

ForkJoinPool.commonPool-worker-4

main

main

ForkJoinPool.commonPool-worker-6

ForkJoinPool.commonPool-worker-7

ForkJoinPool.commonPool-worker-7

ForkJoinPool.commonPool-worker-7

ForkJoinPool.commonPool-worker-7

ForkJoinPool.commonPool-worker-7

Parallel stream processed with 1350ms.

 

Sequential stream processed with 10003ms.

 

通过线程名称可以看出,流以并行模式运行的时候使用到了ForkJoin框架。

那么就更加明确了,当流在并行模式下工作时,JDK使用了多个线程进行并行处理,这将牵扯到多个计算结果合并的问题,所以reduce方法的第三个参数(BinaryOperator.apply)作用是将两个线程的计算结果合并。

 

更多信息参考:http://www.infoq.com/cn/articles/forkjoin-to-parallel-streams

 

至此,Stream基本上都已经搞清楚了,但是我们公司还在使用JDK6,呵呵!

 

分享到:
评论

相关推荐

    java使用stream对日期排序

    首先,我们需要了解Java中的日期时间API。在Java 8之前,我们通常使用`java.util.Date`和`java.text.SimpleDateFormat`来处理日期。然而,这些类存在一些设计上的问题,因此Java 8引入了新的日期时间API,包括`java....

    java8stream源码-Streams:JavaStream概览

    Java 8 引入了一种新的集合...通过深入了解 Java 8 Stream API 及其源码实现,开发者可以更有效地处理大数据,提高代码的可读性和可维护性。在实际项目中,合理运用 Stream API 可以帮助我们写出更优雅、高效的代码。

    Java8 Stream flatmap中间操作用法解析

    今天,我们将深入了解 Java8 Stream flatmap 中间操作的用法解析。 flatmap 操作的定义 在 Java8 的 Stream API 中,flatmap 操作是通过 `flatMap` 方法实现的,该方法的定义如下: `&lt;R&gt; Stream&lt;R&gt; flatMap...

    java8Stream方法简介-源码.rar

    Java 8引入了一种新的集合处理方式,那就是Stream API,它极大地改变了我们处理集合数据的方式,使得代码更加简洁、高效且易于理解。Stream API是Java 8中的一个核心特性,它提供了一种声明式编程风格,可以用于大量...

    如何在java 8 stream表达式实现if/else逻辑

    Java 8 Stream 表达式实现 if/else 逻辑...如果您想了解更多关于Java 8 Stream 表达式和lambda 表达式的知识,可以查看以下资源: * Oracle 的 Java 8 文档 * Java 8 Stream API 的官方文档 * Lambda 表达式的实践指南

    Speedment一个数据库访问库它利用了Java8StreamAPI进行查询

    Speedment的使用首先要求对Java 8有一定的了解,特别是Stream API。Stream API是Java 8引入的新特性,它允许以声明性方式处理集合数据,类似于SQL查询。在Speedment中,数据库查询被转换为Stream操作,这使得在内存...

    深入探讨 Java 8 Stream API 的 Collectors.minBy() 方法

    在 Java 8 引入的 Stream API 中,java.util.stream.Collectors.minBy() 方法是一个强大的工具,用于在集合操作中找到流中按照指定比较器最小的元素。与 maxBy() 方法相对应,minBy() 提供了一种声明式的方式来确定...

    深入探索 Java 8 Stream API 的 Collectors.maxBy() 方法

    在 Java 8 引入的 Stream API 中,Collectors 类提供了多种强大的工具,用于处理集合数据。其中,Collectors.maxBy() 方法尤其引人注目,因为它允许开发者以声明式的方式轻松找到流中的最大元素。本文将深入探讨 ...

    Java 8 Stream API 中的 Collectors.toSet() 深度解析

    在Java 8中引入的Stream API极大地简化了集合的处理,使得代码更加简洁和易于理解。Collectors.toSet()作为Stream API中的一个重要组成部分,它的作用是将流(Stream)中的元素收集到一个集合中,而这个默认集合就是...

    Java 8 Stream API中的`Collectors.collectingAndThen()`:转换结果的利器

    在Java 8引入的Stream API中,Collectors类提供了多种收集器(Collector),用于将流(Stream)的元素汇总成各种形式的结果。Collectors.collectingAndThen()是其中一种强大的收集器,它允许开发者在收集过程完成后...

    Java 8 Stream API 中的 `Collectors.averagingDouble()`:计算平均值的利器

    Java 8 引入的 Stream API 极大地简化了集合操作,其中 Collectors.averagingDouble() 方法为计算平均值提供了一种高效且表达性强的方式。本文将深入探讨 Collectors.averagingDouble() 方法的工作原理、使用场景...

    精通Java 8 Stream的`Collectors.collectingAndThen()`:转换与后处理的艺术

    在Java 8引入的Stream API中,Collectors类提供了一种强大的方式来处理集合数据。Collectors.collectingAndThen()方法尤其独特,它允许开发者在完成基本的收集操作后,对结果进行进一步的转换或后处理。这种方法的...

    官方版本-Java8-中文版-API(帮助你快速了解Java8新特性)

    这份官方版本的Java8中文API文档是开发者了解和掌握这些新特性的宝贵资源。以下是其中的一些关键知识点: 1. **Lambda表达式**:Java 8最大的亮点之一就是引入了Lambda表达式,它简化了函数式编程,使得可以以更...

    探索 Java 8 Stream 中的 `Collectors.groupingByConcurrent()`:并行处理的艺术

    在Java 8中,Stream API 的引入极大地增强了集合的处理能力,尤其是在处理大量数据时。Collectors.groupingByConcurrent() 方法是这一API中一个强大的工具,它允许开发者以并行的方式对数据进行分组,从而提高性能和...

    java8-Stream性能差?不要人云亦云.pdf

    "Java 8 Stream性能优化" 在 Java 8 中,Stream API 是一个非常强大的功能,它可以帮助开发者快速处理大量数据。但是,许多开发者在使用 Stream 时,发现其性能并不是很好。这是因为 Stream 的性能是受到多种因素...

    Java8 jdk安装包

    首先,让我们了解如何安装Java Development Kit (JDK)。JDK是Java开发的基础,包含了编译器、调试工具和其他必要的库。在Windows系统中,Java8的安装通常涉及以下步骤: 1. **下载**:访问Oracle官方网站...

    java8_32.zip

    要深入了解Java 8,可以参考官方文档、教程以及各种在线课程,如Oracle官方教程、Stack Overflow问答、GitHub上的开源项目等,不断提升对Java 8新特性的理解和应用能力。 总之,Java 8的推出极大地推动了Java语言的...

    Stream-2-Stream_1.0_source.rar_java p2p_java stream_stream media

    标签"java_p2p"、"java_stream"、"stream_media_player"和"stream_p2p"分别强调了Java编程语言、流处理、流媒体播放器和P2P流媒体的应用。 P2P技术是一种网络架构,其中每个参与者既是服务的消费者也是服务的提供者...

    java8 中文文档

    - **Stream API**:Java 8 提供了 Stream API,允许对集合进行函数式编程操作,如过滤、映射、归约等。Stream 可以处理数组、集合甚至 I/O 流,极大地提高了数据处理的灵活性。 2. **默认方法**: - 在接口中,...

    Java8 Linux版本

    Java 8是Oracle公司推出的Java开发工具包(Java Development Kit...在Linux环境下,了解如何正确安装和配置Java 8 JDK也是每个开发者的基础技能。同时,要关注安全更新,定期检查和更新JDK版本,以防止潜在的安全风险。

Global site tag (gtag.js) - Google Analytics