JDK 8中的流驱动的集合功能

这篇文章介绍了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得到一个新的StreamInteger由每个发行年份前提是S Movie在原Stream 。 此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

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

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

相关文章

知识汇集

Oracle中锁介绍&#xff1a;http://space.itpub.net/26961876/viewspace-731300转载于:https://www.cnblogs.com/yaohonv/archive/2012/08/18/tech-col.html

jquery mobile 移动web(5)

有序列表   <div data-role"content">     <ol data-role"listview" data-theme"g">       <li><a href"#"> List 1</a></li>       <li><a href"#"> L…

cjmx:JConsole的命令行版本

当监视正在运行的Java应用程序时&#xff0c;JConsole是一个很好的工具。 但是&#xff0c;当无法使用JConsole直接连接到JVM&#xff08;例如&#xff0c;由于网络限制&#xff09;并且无法进行SSH隧道传输时&#xff0c;那么拥有命令行版本的JConsole会很棒。 jcmx是JConsol…

Android中SQLiteDatabase操作【附源码】

像我们做的很多应用程序及网站一样&#xff0c;基本都是对数据库进行增删改查来实现相应的功能。那么Android开发也一样&#xff0c;不过由于在移动客户端应用&#xff0c;所以不会像sql server、mysql那么复杂&#xff0c;Android应用程序支持本地数据库&#xff0c;SQLiteDat…

移动设备HTML5页面布局

在HTML5标准添加的新元素中&#xff0c;用于常见页面结 构的包括header footer footer nav aside aside article section hgroup 。 下面简单介绍一下这个元素&#xff1a; 1.header header>元素定义文档的页面组合&#xff0c;通 常是一些引导和导航信息&#xff0c;标签…

Hazelcast入门指南第5部分

这是我撰写的有关Hazelcast的一系列文章的延续。 我强烈建议您阅读其他内容&#xff1a; 第1 部分 &#xff0c; 第2 部分 &#xff0c; 第3 部分和第4部分 。 让人一见倾心的东西&#xff1f; 这篇文章中将没有Hazelcast专用代码。 让我重复一遍。 这篇文章中将没有Hazelcast…

【BEV感知算法概述——下一代自动驾驶感知算法】

文章目录 BEV感知算法概念BEV感知算法数据集介绍BEV感知算法分类BEV感知算法的优劣小结 BEV感知算法概念 Bird’s-Eye-View&#xff0c;鸟瞰图&#xff08;俯视图&#xff09;。BEV感知算法存在许多的优势。 首先&#xff0c;BEV视图存在遮挡小的优点&#xff0c;由于视觉的透…

jquery鼠标事件

click()   为点击事件绑定一个事件处理函数&#xff0c;或者触发元素点击事件。   .click( handler(eventObject) )     handler(eventObject)       每次事件触发时候执行的函数。   .click([eventData],handler(eventObject))     eventData      …

[LaunchPad] 超声波测试,数码管显示

1 #include "io430g2553.h"2 3 unsigned char Disp_Tab[] {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //段码控制 4 unsigned char dispbit[8]{0xfe,0xfd,0xfb,0xf7,0xef,0xdF,0xbF,0x7F}; //位选控制 5 6 unsigned char LedOut[4];7 8 …

Spring的依赖注入陷阱

Spring框架中有三种注入变量&#xff1a; 基于二传手的注射 基于构造函数的注入 基于现场的注入 这些机制中的每一种都有优点和缺点&#xff0c;并且不仅只有一种正确的方法。 例如现场注入&#xff1a; Autowired private FooBean fooBean;在生产代码中使用它通常不是最好…

jquery 操作css 选择器

.addClass()   为每个匹配的元素添加指定的样式类名   .addClass(className)     className 为每个匹配元素所有增加的一个或多个样式名   .addClass(function(index,currentClass))     函数返回一个或者多个用空格隔开&#xff0c; index 表示参数匹配中的索引…

vim设置

一、基本编辑功能1、复制、剪切和粘贴复制特定的某一段&#xff1a;把光标移到要复制的文本的头部&#xff0c;按下“v”&#xff0c;往后移动光标&#xff0c;光标所过之处的字符>都会高亮&#xff0c;移到欲复制文本的尾部后&#xff0c;按下“y”&#xff0c;高亮文本全部…

jquery表单属性筛选元素

$(":button") 选择所有按钮元素类型为按钮的元素。 等于$(input[type"button"]) $(":checkbox") 选择所有类型为复选框的元素。 等于$(input[type"checkbox"]) $(":checked") 选择所有勾选的元素。 $( "input:checked&…

Hamcrest Matchers的高级创建

介绍 上一次 &#xff0c;我讨论了Hamcrest Matcher是什么&#xff0c;如何使用以及如何制作。 在本文中&#xff0c;我将解释创建Hamcrest Matchers的更多高级步骤。 首先&#xff0c;我将分享如何使您的匹配器更易于类型安全&#xff0c;然后介绍无状态匹配器的一些技术&…

嵌入式成长轨迹37 【Zigbee项目】【CC2430基础实验】【自动闪烁】

最为简单的代码&#xff0c;只用到一个寄存器P1DIR。因为点亮的led灯&#xff08;p1.0和p1.1&#xff09;的管脚是p1的&#xff0c;要输出就得将这两个管脚设置为输出管脚。该寄存器用0~8对应1.0~1.8管脚。 1 //main.c2 #include <ioCC2430.h>3 4 #define uint unsigned …

博客园CodingLife模板样式优化

博客园CodingLife模板样式优化&#xff0c;小屏和大屏均做了优化&#xff0c;感兴趣的园友可以复制到你的页面定制CSS代码中&#xff0c; 源码地址&#xff1a;http://www.cnblogs.com/blog/customcss/334547.css 更多专业前端知识&#xff0c;请上 【猿2048】www.mk2048.com

如何允许用户自定义UI

理念 利用JavafX / FXML的声明性设计模式&#xff0c;并允许用户仅通过使用例如SceneBuilder打开某个视图即可重新定制布局或添加新控件&#xff0c;甚至根据用户需要更改样式&#xff0c;从而无需任何编码即可自定义某个视图。 FXML文件 CSS基本上可以放置在通过URL可以到达的…

WPF控件和布局

WPF控件和布局&#xff0c;根据刘铁猛《深入浅出WPF》书籍讲解内容&#xff0c;主要记录控件和布局的原理&#xff0c;如果有不足的地方&#xff0c;请大牛们键盘下留情--轻喷&#xff01;如果还算有用&#xff0c;请给点动力&#xff0c;支持一把&#xff01; 一、WPF里的控件…

css背景图片定位

背景图默认平铺&#xff1a; background-repeat: no-repeat;/*不平铺*//*repeat-x;沿X轴平铺*//*repeat-x;沿Y轴平铺*/ 背景图片定位&#xff1a; background-position: 100px 30px;/* X轴 Y轴 *//* 20% 20%; 百分比的方式 *//* left|center|right top|center|bottom */ 背景中…

使用GZIP和压缩数据

抽象 我们都知道用zip或gzip压缩文件的含义。 但是在Java中使用压缩文件并不像您想的那样简单明了&#xff0c;尤其是当您不是直接使用文件而是压缩流数据时。 我们会去&#xff1a; 如何将字符串转换为压缩/压缩字节数组&#xff0c;反之亦然 创建用于读取和写入文件的实用程…