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” SetStream上调用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 ,它将指示将流结果安排在SetStream.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可基于底层SetMovie对象),并应用所提供的功能针对Steam返回一个新的Stream ,从结果该Function对源Stream 。 在这种情况下, FunctionMovie::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的发行年份提供的。 此StreamInteger当时的具有Stream.reduce(BinaryOperation)与静态执行的操作Integer用作方法BinaryOperation

对于此代码清单,我在计算最旧的电影( Integer.min(int,int) )时故意在PredicateBinaryOperation中使用了lambda表达式,并在计算最新电影时使用了PredicateBinaryOperation方法引用,而不是使用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集合类流

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/338671.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言可变参数只会用算啥本事?看我来抽丝剥茧干翻它!

看山是山&#xff0c;看山不是山&#xff0c;最终看山才是山&#xff0c;并且是无穷的山峦。当我们学习一门技术的时候&#xff0c;起初是先模仿&#xff0c;但是最终是为了超越&#xff0c;也就是得到秘籍&#xff0c;看到本质。于是&#xff0c;今天来继续看可变参数&#xf…

Linux下CMAKE编译jsoncpp,使用CMake引入jsoncpp

在jni的cpp中使用json&#xff0c;百度了一下&#xff0c;大多都是下面这个库&#xff0c;但是和之前的文档有点出入了&#xff0c;记录一下。jsoncpp库地址&#xff1a;添加jsoncpp库在cpp目录下创建一个jsoncpp目录下载jsoncpp项目把src\lib_json文件夹下的文件都拉到项目的c…

python打印星星居中_python实现while循环打印星星的四种形状

在控制台连续输出五行*,每一行星号数量一次递增***************#1.定义一个行计数器row 1while row < 5:#定义一个列计数器col 1#开始循环while col < row:print(*,end)col 1print()row 1如果想要星星倒过来呢#1.定义一个行计数器row 1while row < 5:#定义一个列…

java8升级java12_为什么现在是升级到Java 8的最佳时机

java8升级java12有兴趣了解如何通过AppDynamics充分利用Java 8的新功能吗&#xff1f; 立即开始免费试用 &#xff01; 今年3月&#xff0c;Oracle发布了近十年来最受期待的版本Java8。自发布以来&#xff0c;最新版本引起了越来越多的关注&#xff0c;各种规模的公司都渴望升…

C语言#include还有些你不知道的事

#include简介在C语言中#include是preprocessor的一条指令&#xff0c;告诉预处理器将指定头文件的内容插入到预处理器命令的相应位置。#include "xxx.h" 和 #include有两种方式可以指定插入头文件&#xff1a;#include #include "filename"如果需要包含标…

java常见的ide_在三个Java IDE中生成的三种常见方法

java常见的ide在本文中&#xff0c;我研究了NetBeans 8.0.2 &#xff0c; IntelliJ IDEA 14.0.2和Eclipse Luna 4.4.1生成的三种“通用”方法[ equals&#xff08;Object&#xff09; &#xff0c; hashCode&#xff08;&#xff09;和toString&#xff08;&#xff09; ]的区别…

深度linux安装依赖,Linux -- Ubuntu下载deepin wine依赖问题笔记

问题开始下载deepin-wine安装包, 请稍后…1.1udis86_1.72-2_i3 100%[>] 34.18K 87.3KB/s 用时 0.4s1.2deepin-fonts-win 15%[> ] 31.18K 1.72KB/s 用时 18s1.2deepin-fonts-win 100%[>] 207.88K 26.2KB/s 用时 6.7s2.1deepin-libwine_2 100%[>] 18.97M 132KB/s 用时…

什么是C语言中的隐式函数声明?

「1、什么是C语言的隐式函数声明」在C语言中&#xff0c;函数在调用前不一定非要声明。如果没有声明&#xff0c;那么编译器会自动按照一种隐式声明的规则&#xff0c;为调用函数的C代码产生汇编代码。下面是一个例子&#xff1a;int main(int argc, char** argv) {double x a…

群晖 上传 源文件不存在_群晖NAS连接百度网盘报错?原因是这样的

群晖NAS附带的云同步套件可以与国内外多个网盘连接 , 连接后可从云上下载数据亦可从本地将数据上传到云上。例如通过云同步套件连接百度网盘账号后可以便捷上传和下载数据 , 若网盘空间较大甚至可用来备份整个NAS等。不过现在看来群晖与百度网盘的合作似乎已经结束&#xff0c;…

ssl/tls服务器瞬时_SSL / TLS REST服务器–带有Spring和TomEE的客户端

ssl/tls服务器瞬时在构建系统时&#xff0c;开发人员通常会忽略安全性方面。 安全一直是令人担忧的重要问题&#xff0c;但是它比以前吸引了更高的关注。 就在今年&#xff0c;我们发生了像Heartbleed Bug或CelebrityGate丑闻这样的案件。 这与帖子无关&#xff0c;只是安全真正…

linux kvm百度云,容器与云|如何在 Ubuntu Linux 上使用 KVM 云镜像

如何下载并使用运行在 Ubuntu Linux 服务器上的 KVM 云镜像&#xff1f;如何在 Ubuntu Linux 16.04 LTS 服务器上无需完整安装即可创建虚拟机&#xff1f;如何在 Ubuntu Linux 上使用 KVM 云镜像&#xff1f;基于内核的虚拟机(KVM)是 Linux 内核的虚拟化模块&#xff0c;可将其…

C 的16个大坑,你能躲过几个?

首先说下C 和C语言有什么区别&#xff1f;分享一个我在知乎上看见的回答&#xff1a;C ≈ C with classes&#xff0c; C with STLC&#xff1a;面向机器编程C &#xff1a;面向编译器编程C 有个很重要的特性叫RAII&#xff0c;个人认为可以多多使用&#xff0c;相当方便。言归…

python占位符怎么输入_python占位符怎么输入

占位符&#xff0c;顾名思义就是插在输出里站位的符号。占位符是绝大部分编程语言都存在的语法&#xff0c; 而且大部分都是相通的&#xff0c; 它是一种非常常用的字符串格式化的方式。1、常用占位符的含义s : 获取传入对象的__str__方法的返回值&#xff0c;并将其格式化到指…

java 性能调优_Java性能调优调查结果(第三部分)

java 性能调优这是本系列文章的第三篇&#xff0c;我们将分析2014年10月进行的调查的结果。如果您尚未这样做&#xff0c;我建议从本系列的前两篇文章开始&#xff1a; 问题严重性分析和监视域分析 。 这篇文章着重于故障排除/根本原因检测。 本调查部分的背景&#xff1a;意识…

不懂指针类型,7个例子给你讲明白

1. int va;这是一个整型变量&#xff0c;32位CPU的话&#xff0c;占有32个bite2. int *va;这是一个整型指针变量&#xff0c;用于存放一个整型变量的地址&#xff0c;3. int **va;这是一个整型的二级指针&#xff0c;用于存放一个内存的地址&#xff0c;该地址对应的内存中存放…

linux ffmpeg yum源,ffmpeg最新的yum源地址及视频去logo

一&#xff1a;ffmpeg 最新yum源cat /etc/yum.repo.d/atrpms.repo[atrpms]nameRed Hat Enterprise Linux $releasever - $basearch - ATrpmsfailovermethodprioritybaseurlhttp://dl.atrpms.net/el$releasever-$basearch/atrpms/stableenabled1gpgcheck0gpgkeyfile:///etc/pki/…

Tomcat与Netty比较

Tomcat介绍Tomcat支持的协议Tomcat的优缺点Netty介绍Netty支持的协议Netty的优点和缺点Tomcat和Netty的区别Tomcat和Netty的应用场Tomcat和Netty来处理大规模并发连接的优化Tomcat与Netty的网络模型的区别Tomcat与Netty架构设计拓展 Tomcat介绍 Tomcat是一个免费的、开放源代码…

spring 项目集成配置_Spring重试–与项目集成的方式

spring 项目集成配置如果您需要在代码中实现健壮的重试逻辑&#xff0c;一种行之有效的方法是使用spring重试库。 我的目的不是要展示如何使用spring retry项目本身&#xff0c;而是要演示将其集成到代码库中的不同方式。 考虑一种服务来调用外部系统&#xff1a; package re…

redis 内存不足 排查_排查redis占用内存达90%以上

帮别人排查一个问题,项目还没上线但redis占用内存很高。思路如下&#xff1a;1、登陆redis控制台&#xff0c;首先用 keys * 获取所有的key> keys *x:x:ax:x:bx:x:c发现key也就十来个&#xff0c;用 TYPE x:x:a 发现a是一个list数据类型用lrange命令查看list中指定索引的值用…

C或C 如何通过程序执行shell命令并获取命令执行结果?

1 应用场景最近在实际程序开发中&#xff0c;需要通过程序执行 shell 命令&#xff0c;并获取命令输出内容。但是系统自带的 system 只能返回命令执行成功与否&#xff0c;不能捕获命令输出。2 扩展性由于应用场景本就广泛&#xff0c;因此扩展性较好。此函数可以执行任意命令&…