jdk8集合类流_JDK 8中的流驱动的集合功能
jdk8集合类流
这篇文章介绍了JDK 8的应用–引入了带有集合的 流 ,以更简洁地完成通常需要的与集合相关的功能。 在此过程中,将演示并简要说明使用Java Streams的几个关键方面。 请注意,尽管JDK 8 Streams通过并行化支持提供了潜在的性能优势,但这并不是本文的重点。
样品采集和采集条目
就本文而言, Movie
实例将存储在一个集合中。 以下代码段适用于这些示例中使用的简单Movie
类。
电影.java
package dustin.examples.jdk8.streams;import java.util.Objects;/*** Basic characteristics of a motion picture.* * @author Dustin*/
public class Movie
{/** Title of movie. */private String title;/** Year of movie's release. */private int yearReleased;/** Movie genre. */private Genre genre;/** MPAA Rating. */private MpaaRating mpaaRating;/** imdb.com Rating. */private int imdbTopRating;public Movie(final String newTitle, final int newYearReleased,final Genre newGenre, final MpaaRating newMpaaRating,final int newImdbTopRating){this.title = newTitle;this.yearReleased = newYearReleased;this.genre = newGenre;this.mpaaRating = newMpaaRating;this.imdbTopRating = newImdbTopRating;}public String getTitle(){return this.title;}public int getYearReleased(){return this.yearReleased;}public Genre getGenre(){return this.genre;}public MpaaRating getMpaaRating(){return this.mpaaRating;}public int getImdbTopRating(){return this.imdbTopRating;}@Overridepublic boolean equals(Object other){if (!(other instanceof Movie)){return false;}final Movie otherMovie = (Movie) other;return Objects.equals(this.title, otherMovie.title)&& Objects.equals(this.yearReleased, otherMovie.yearReleased)&& Objects.equals(this.genre, otherMovie.genre)&& Objects.equals(this.mpaaRating, otherMovie.mpaaRating)&& Objects.equals(this.imdbTopRating, otherMovie.imdbTopRating);}@Overridepublic int hashCode(){return Objects.hash(this.title, this.yearReleased, this.genre, this.mpaaRating, this.imdbTopRating);}@Overridepublic String toString(){return "Movie: " + this.title + " (" + this.yearReleased + "), " + this.genre + ", " + this.mpaaRating + ", "+ this.imdbTopRating;}
}
Movie
多个实例放置在Java Set中 。 下面显示了执行此操作的代码,因为它还显示了在这些实例中设置的值。 此代码在类上将“电影”声明为静态字段,然后使用静态初始化块用五个Movie
实例填充该字段。
使用电影类实例填充电影集
private static final Set<Movie> movies;static
{final Set<Movie> tempMovies = new HashSet<>();tempMovies.add(new Movie("Raiders of the Lost Ark", 1981, Genre.ACTION, MpaaRating.PG, 31));tempMovies.add(new Movie("Star Wars: Episode V - The Empire Strikes Back", 1980, Genre.SCIENCE_FICTION, MpaaRating.PG, 12));tempMovies.add(new Movie("Inception", 2010, Genre.SCIENCE_FICTION, MpaaRating.PG13, 13));tempMovies.add(new Movie("Back to the Future", 1985, Genre.SCIENCE_FICTION, MpaaRating.PG, 49));tempMovies.add(new Movie("The Shawshank Redemption", 1994, Genre.DRAMA, MpaaRating.R, 1));movies = Collections.unmodifiableSet(tempMovies);
}
初探带有过滤的JDK 8流
通常在集合上执行的一种功能是过滤。 下一个代码清单显示了如何过滤所有评级为PG的电影的“电影” Set
。 列出之后,我将重点介绍可以从此代码中得出的一些观察结果。
使用PG分级过滤电影
/*** Demonstrate using .filter() on Movies stream to filter by PG ratings* and collect() as a Set.*/
private void demonstrateFilteringByRating()
{printHeader("Filter PG Movies");final Set<Movie> pgMovies =movies.stream().filter(movie > movie.getMpaaRating() == MpaaRating.PG).collect(Collectors.toSet());out.println(pgMovies);
}
第一个示例包括本文中的所有示例也将具有的一件事是在集合上调用stream()方法。 此方法返回一个实现java.util.Stream接口的对象。 这些返回的每个Streams均使用针对其调用stream()
方法的集合作为其数据源。 此时的所有操作都在Stream
上,而不是在集合上,后者是Stream
的数据源。
在上面的代码清单中,基于“ movies” Set
在Stream
上调用filter ( Predicate )方法。 在这种情况下, Predicate
由lambda表达式 movie -> movie.getMpaaRating() == MpaaRating.PG
。 这种相当可读的表示法告诉我们,谓词是基础数据中具有MPAA等级PG的每部电影。
Stream.filter(Predicate)方法是一个中间操作 ,意味着它返回Stream
的实例,该实例可以由其他操作进一步操作。 在这种情况下,还有另一个操作collect(Collector) ,该操作在Stream.filter(Predicate)
返回的Stream
上调用。 Collectors类具有许多静态方法,每个方法都提供一个Collector的实现,可以将其提供给此collect(Collector)
方法。 在这种情况下,使用Collectors.toSet()获得一个Collector
,它将指示将流结果安排在Set
。 Stream.collect(Collector)
方法是一个终端操作 ,这意味着它是该行的结尾,并且不返回Stream
实例,因此在执行此collection之后无法再执行任何Stream
操作。
执行以上代码后,它将生成如下输出:
===========================================================
= Filter PG Movies
===========================================================
[Movie: Raiders of the Lost Ark (1981), ACTION, PG, 31, Movie: Back to the Future (1985), SCIENCE_FICTION, PG, 49, Movie: Star Wars: Episode V - The Empire Strikes Back (1980), SCIENCE_FICTION, PG, 12]
过滤单个(第一个)结果
/** * Demonstrate using .filter() on Movies stream to filter by #1 imdb.com* rating and using .findFirst() to get first (presumably only) match.*/
private void demonstrateSingleResultImdbRating()
{printHeader("Display One and Only #1 IMDB Movie");final Optional<Movie> topMovie =movies.stream().filter(movie -> movie.getImdbTopRating() == 1).findFirst();out.println(topMovie.isPresent() ? topMovie.get() : "none");
}
这个例子与前面的例子有很多相似之处。 像之前的代码清单一样,该清单显示了Stream.filter(Predicate)
的Stream.filter(Predicate)
,但是这次谓词是lambda表达式movie -> movie.getImdbTopRating() == 1)
。 换句话说,从此过滤器生成的Stream
应该只包含具有方法getImdbTopRating()
返回数字1的Movie
实例。然后,对Stream.filter(Predicate)
返回的Stream
执行终止操作Stream.findFirst( Stream.filter(Predicate)
。 这将返回流中遇到的第一个条目,并且由于我们的基础Movie
Set
实例只有一个IMDb Top 250 Rating为1的实例,因此它将是流中第一个也是唯一一个由过滤器生成的条目。
执行此代码清单后,其输出如下所示:
===========================================================
= Display One and Only #1 IMDB Movie
===========================================================
Movie: The Shawshank Redemption (1994), DRAMA, R, 1
下一个代码清单说明了Stream.map(Function)的用法 。
/*** Demonstrate using .map to get only specified attribute from each* element of collection.*/
private void demonstrateMapOnGetTitleFunction()
{printHeader("Just the Movie Titles, Please");final List<String> titles = movies.stream().map(Movie::getTitle).collect(Collectors.toList());out.println(titles.size() + " titles (in " + titles.getClass() +"): " + titles);
}
该Stream.map(Function)
方法作用于Stream
对调用它(在我们的例子中, Stream
可基于底层Set
的Movie
对象),并应用所提供的功能针对Steam
返回一个新的Stream
,从结果该Function
对源Stream
。 在这种情况下, Function
由Movie::getTitle
表示,这是JDK 8引入的方法reference的示例。 我可以使用lambda表达式movie -> movie.getTitle()
代替方法参考Movie::getTitle
来获得相同的结果。 方法参考文档解释说,这正是方法参考旨在解决的情况:
您使用lambda表达式创建匿名方法。 但是,有时lambda表达式除了调用现有方法外什么也不做。 在这种情况下,通常更容易按名称引用现有方法。 方法引用使您可以执行此操作; 它们是紧凑的,易于阅读的lambda表达式,用于已经具有名称的方法。
从上面的代码中您可能会猜到它, Stream.map(Function)
是一个中间操作。 就像前面两个示例一样,此代码清单应用了Stream.collect(Collector)
的终止操作,但是在这种情况下,是传递给它的是Collectors.toList() ,因此结果数据结构是List而不是Set
。
当上面的代码清单运行时,其输出如下所示:
===========================================================
= Just the Movie Titles, Please
===========================================================
5 titles (in class java.util.ArrayList): [Inception, The Shawshank Redemption, Raiders of the Lost Ark, Back to the Future, Star Wars: Episode V - The Empire Strikes Back]
减少(转换为单布尔)操作anyMatch和allMatch
下一个示例不使用在大多数先前示例中使用的Stream.filter(Predicate)
, Stream.map(Function)
甚至终止操作Stream.collect(Collector)
。 在此示例中,基于我们的Movie
对象Set
,缩减和终止操作Stream.allMatch(Predicate)和Stream.anyMatch(Predicate)直接应用于Stream
。
/*** Demonstrate .anyMatch and .allMatch on stream.*/
private void demonstrateAnyMatchAndAllMatchReductions()
{printHeader("anyMatch and allMatch");out.println("All movies in IMDB Top 250? " + movies.stream().allMatch(movie -> movie.getImdbTopRating() < 250));out.println("All movies rated PG? " + movies.stream().allMatch(movie -> movie.getMpaaRating() == MpaaRating.PG));out.println("Any movies rated PG? " + movies.stream().anyMatch(movie -> movie.getMpaaRating() == MpaaRating.PG));out.println("Any movies not rated? " + movies.stream().anyMatch(movie -> movie.getMpaaRating() == MpaaRating.NA));
}
该代码清单说明Stream.anyMatch(Predicate)
和Stream.allMatch(Predicate)
各自返回一个布尔值,分别表示其名称是否暗示Stream
具有至少一个与谓词匹配的条目还是所有与谓词匹配的布尔值。 在这种情况下,所有电影都来自imdb.com前250名,因此“ allMatch”将返回true
。 但是,并非所有电影都被评为PG,因此“ allMatch”返回false
。 由于至少有一部电影被评为PG,因此PG评级谓词的“ anyMatch”返回true
,但N / A评级谓词的“ anyMatch”返回false
因为即使底层Set
没有一部电影也具有MpaaRating.NA
评级。 接下来显示运行此代码的输出。
===========================================================
= anyMatch and allMatch
===========================================================
All movies in IMDB Top 250? true
All movies rated PG? false
Any movies rated PG? true
Any movies not rated? false
轻松确定最小和最大
本文中将Stream
的强大功能应用于集合操作的最后一个示例演示了Stream.reduce(BinaryOperator)与BinaryOperator的两个不同实例的结合使用 : Integer :: min和Integer :: max 。
private void demonstrateMinMaxReductions()
{printHeader("Oldest and Youngest via reduce");// Specifying both Predicate for .map and BinaryOperator for .reduce with lambda expressionsfinal Optional<Integer> oldestMovie = movies.stream().map(movie -> movie.getYearReleased()).reduce((a,b) -> Integer.min(a,b));out.println("Oldest movie was released in " + (oldestMovie.isPresent() ? oldestMovie.get() : "Unknown"));// Specifying both Predicate for .map and BinaryOperator for .reduce with method referencesfinal Optional<Integer> youngestMovie = movies.stream().map(Movie::getYearReleased).reduce(Integer::max);out.println("Youngest movie was released in " + (youngestMovie.isPresent() ? youngestMovie.get() : "Unknown"));
}
这个复杂的示例说明了如何使用Integer.min(int,int)
在基础Set
查找最旧的电影,以及使用Integer.max(int,int)
在Set
查找最新的电影。 这是通过首先使用Stream.map
获取新的Integer
Stream
来完成的,该新的Integer
Stream
是由原始Stream
中每个Movie
的发行年份提供的。 此Stream
的Integer
当时的具有Stream.reduce(BinaryOperation)
与静态执行的操作Integer
用作方法BinaryOperation
。
对于此代码清单,我在计算最旧的电影( Integer.min(int,int)
)时故意在Predicate
和BinaryOperation
中使用了lambda表达式,并在计算最新电影时使用了Predicate
和BinaryOperation
方法引用,而不是使用lambda表达式。 Integer.max(int,int)
)。 这证明lambda表达式或方法引用可以在许多情况下使用。
接下来显示运行上述代码的输出:
===========================================================
= Oldest and Youngest via reduce
===========================================================
Oldest movie was released in 1980
Youngest movie was released in 2010
结论
JDK 8 Streams引入了一种强大的机制来处理Collections。 与直接使用Collections相比,这篇文章侧重于使用Streams带来的可读性和简洁性,但是Streams也具有潜在的性能优势。 这篇文章试图使用常见的集合处理习惯用法作为Streams带给Java简洁性的示例。 在此过程中,还讨论了与使用JDK流相关的一些关键概念。 使用JDK 8 Streams最具挑战性的部分是适应了新概念和新语法(例如lambda表达式和方法引用),但是在玩了几个示例之后很快就学到了这些。 一位对概念和语法有很丰富经验的Java开发人员可以探索Stream API的方法,以获取比本博文中所示的针对Streams(并因此针对基于Streams的集合)执行的操作更长的列表。
其他资源
这篇文章的目的是基于简单但相当普遍的collections操纵示例简要介绍JDK 8流。 要更深入地了解JDK 8流,以及有关JDK 8流如何使Collections操作更容易的更多想法,请参见以下文章:
- 使用Java SE 8流处理数据,第1部分
- 第2部分:使用Java SE 8流处理数据
- 本杰明·温特伯格的Java 8流教程
- David Hartveld 的Stream API简介
- Java 8 Streams入门
- Java Tutorial的Collections on Streams 聚合操作
- Java Tutorial的Collections 减少流
- Java Tutorial的Collections on Streams 并行性
- Lambda表达式的语法
- 方法参考
翻译自: https://www.javacodegeeks.com/2015/01/stream-powered-collections-functionality-in-jdk-8.html
jdk8集合类流
jdk8集合类流_JDK 8中的流驱动的集合功能相关推荐
- 【Java网络编程与IO流】Java中IO流分为几种?字符流、字节流、缓冲流、输入流、输出流、节点流、处理流
Java网络编程与IO流目录: [Java网络编程与IO流]Java中IO流分为几种?字符流.字节流.缓冲流.输入流.输出流.节点流.处理流 [Java网络编程与IO流]计算机网络常见面试题高频核心考 ...
- java8 流操作_java8中的流操作
Stream 流是 Java 8 新提供给开发者的一组操作集合的 API,将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选.排序.聚合等.元素流在管道中经过 ...
- java io流区别_Java中IO流的分类和BIO,NIO,AIO的区别
到底什么是IO 我们常说的IO,指的是文件的输入和输出,但是在操作系统层面是如何定义IO的呢?到底什么样的过程可以叫做是一次IO呢? 拿一次磁盘文件读取为例,我们要读取的文件是存储在磁盘上的,我们的目 ...
- JDK 8中的流驱动的集合功能
这篇文章介绍了JDK 8的应用–引入了带有集合的 流 ,以更简洁地完成通常需要的与集合相关的功能. 在此过程中,将演示并简要说明使用Java Streams的几个关键方面. 请注意,尽管JDK 8 S ...
- 【JDK8 新特性 6】收集Stream流中的结果
上一篇文章 : (9条消息) [JDK8 新特性 5]Stream流介绍和常用方法的使用_一切总会归于平淡的博客-CSDN博客 目录 1.Stream流中的结果到集合中 2.Stream流中的结果到数 ...
- JDK8新特性(十一)之收集Stream流中的结果
1.Stream流中的数据收集到集合中 Stream流提供collect方法,其参数需要一个java.util.stream.Collector<T,A,R>接口对象来指定收集到哪种集合中 ...
- java中IO流详解
不断更新中!!! 1.流的定义及分类 流是个抽象的概念,是对输入输出设备的抽象,Java程序中,对于数据的输入/输操作都是以"流"的方式进行.设备可以是文件,网络,内存等.将数据从 ...
- stream流常用方法_Java8 中用法优雅的 Stream,怪不得我之前总是看不懂别人写的代码!...
Java8的新特性主要是Lambda表达式和流,当流和Lambda表达式结合起来一起使用时,因为流申明式处理数据集合的特点,可以让代码变得简洁易读 放大招,流如何简化代码 如果有一个需求,需要对数据库 ...
- spark 获取广播变量_Spark流式程序中广播变量和累加器为何使用单例模式
Spark中广播变量详解以及如何动态更新广播变量mp.weixin.qq.com 1.广播变量是只读的,使用单例模式可以减少Spark流式程序中每次job生成执行,频繁创建广播变量带来的开销 2. ...
最新文章
- 作业05-继承、多态、抽象类与接口
- pandas索引复合索引dataframe数据、索引其中一个水平(level)的所有数据行(index all rows in a level)
- Java 获取操作系统名字、系统版本、cpu信息
- 基于VMM的Rootkit检测技术及模型分析
- cpu烤机工具_MySQL常用工具选择和建议
- minio分布式集群示例: 4节点,每节点4块盘
- VTK:图片之ImageSobel2D
- ABAP正则表达式 vs SPLIT INTO
- Linux shell中的一个问题 ${}带正则匹配的表达式
- angular路由操作中'#'字符的解决办法
- 自学Linux命令的四种方法
- Spring 无缝整合 quartz
- python网络编程学习笔记(6):Web客户端访问
- iOS (导航条)navBar 透明
- delphi中exit,abort,break,continue 的区别
- 新版Excel和Word全屏打印预览的设定方法
- MySQL字符串拼接、分组拼接字符串
- AI CC2019安装
- dp算法之平安果路径问题c++
- 斯蒂夫·乔布斯《你必须要找到你所爱的东西》