【使用forEach()结合Lambda表达式遍历集合】

public class ForEachDemo {
public static void main(String[] args) {
Collection<String> list=new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Tomato");
     //调用forEach()方法来遍历集合
list.forEach(obj->System.out.println(obj));
}
}

【关于forEach(Consumer action)方法】

  Java8为Iterable接口新增了一个forEach(Consumer action)默认方法,该方法的参数类型Consumer是一个函数式接口,而Iterable接口是Collection的父接口,因此Collection可以直接调用该方法。

  当程序调用Iterable的forEach(Consumer action)方法遍历集合元素时,程序会依次将集合元素传给Consumer的accept(T t)方法(该接口中唯一的抽象方法),Consumer是一个函数式接口,所以可以使用Lambda表达式来遍历集合元素。

【Java8新增的Predicate操作集合】

Java8为Collection集合新增了一个removeIf(Predicate filter)方法,该方法会删除符合filter条件的所有元素。

该方法需要一个Predicate对象作为参数,Predicate也是函数式接口,因此可以使用Lambda表达式作为参数。

package com.Hggin.ForEach;

import java.util.ArrayList;
import java.util.Collection; public class PredicateDemo {
public static void main(String[] args) {
Collection<String> books=new ArrayList<>();
books.add("《Java编程思想》");
books.add("《Java并发编程》");
books.add("《Java多线程实战》");
books.add("《Spring实战》");
books.add("《Spring技术内幕》");
books.add("《大话数据结构》");
books.add("《大话设计模式》");
books.add("《设计模式之禅》"); /**
* 使用Lambda表达式(目标类型是Predicate)过滤集合
* 移除所有带"Java"字符串的集合元素
*/
books.removeIf(book->((String)book).contains("Java"));
for(String b:books){
System.out.println("-----"+b);
} /**
* 使用Lambda表达式(目标类型是Predicate)过滤集合
* 移除所有字符串以"《大话"开头的集合元素
*/
books.removeIf(book->((String)book).startsWith("《大话"));
for(String b:books){
System.out.println("====="+b);
} }
}

【运行结果】

【分析】

上面调用了Collection集合的removeIf()方法批量删除集合中符合条件的元素,程序传入一个Lambda表达式作为过滤条件:所有满足条件的元素都会被删除。

【Predicate的test()方法的过滤统计作用】

public static void main(String[] args) {
Collection<String> books=new ArrayList<>();
books.add("《Java编程思想》");
books.add("《Java并发编程》");
books.add("《Java多线程实战》");
books.add("《Spring实战》");
books.add("《Spring技术内幕》");
books.add("《大话数据结构》");
books.add("《大话设计模式》");
books.add("《设计模式之禅》");
books.add("《我是一个长度很长长长长长长长长长长长长长长长长长长的书名》");
books.add("《我也是一个长度很长长长长长长长长长长长长长长长长长长的书名》"); //统计含有"Spring"的子串的书名
System.out.println(callAll(books,book->((String)book).contains("Spring"))); //统计含有"Java"的子串的书名
System.out.println(callAll(books,book->((String)book).contains("Java"))); //统计
System.out.println(callAll(books,book->((String)book).length()>)); } /**
* 统计books集合中满足某个条件的集合元素的数量
* 使用Predicate判断每个集合元素是否满足特定的条件
* 该条件是通过Predicate参数动态传入
*/
public static int callAll(Collection books,Predicate p){
int total=;
for(Object obj:books){
if(p.test(obj)){ //只会统计满足条件的对象
total++;
}
}
return total;
}

【运行结果】

【分析】

Java8在java.util.function包下预定以的典型接口之一xxxPredicate接口,通常包含一个test()抽象方法,该方法常用于对参数进行某种判断(test()方法的判断逻辑由Lambda表达式的方式实现),然后返回一个boolean值。该Predicate函数式接口常用语判断参数是否满足特定条件,常用于数据的筛选。

【Java8新增的流式API——Stream操作集合】

Java8新增了Stream、IntStream、LongStream、DoubleStream等流式API,这些API代表多个支持串行和并行聚集操作的元素。

Stream是一个通用的流接口,而IntStream、LongStream、DoubleStream则代表元素的类型为int、long、double的流。

Java8还为每个流式API提供了对应的Builder,例如Stream.Builder、IntStream.Builder,可以使用这些Builder来创建对应的流。

【独立使用Stream流的步骤】

1.使用Stream或XxxStream的builder()类方法创建该Stream对应的Builder。

2.重复调用Builder的add()方法向该流中添加多个元素。

3.调用Builder的build()方法获取对应的Stream。

4.调用Stream的聚集方法。

【关于聚集方法】

上面第4步可以根据具体需求来调用不同的方法,Stream提供了大量的聚集方法供用户调用。

注意:对于大部分聚集方法而言,每个Stream只能执行一次!!!

【实例】

public static void main(String[] args) {
IntStream intS=IntStream.builder()
.add()
.add()
.add(-)
.add()
.build();
//下面调用聚集方法的代码每次只能执行一次,执行多个会报错!!!执行某个方法时记得注释其它方法!!
System.out.println("intS流中所有元素的最大值:"+intS.max().getAsInt()); //
System.out.println("intS流中所有元素的最小值:"+intS.min().getAsInt()); //-16
System.out.println("intS流中所有元素的总和:"+intS.sum()); //
System.out.println("intS流中所有元素的总数:"+intS.count()); //
System.out.println("intS流中所有元素的平均值:"+intS.average()); //OptionalDouble[4.75]
System.out.println("intS流中所有元素的平方是否都大于100:"+intS.allMatch(ele->ele*ele>)); //false
System.out.println("intS流中含有任何元素的平方是否大于100:"+intS.anyMatch(ele->ele*ele>)); //true //将intS映射成一个新的Stream,新Stream的每个元素是原Stream每个元素+1
IntStream newIntS=intS.map(ele->ele+);
//遍历集合元素:使用Lambda表达式的方式
newIntS.forEach(ele->System.out.print("----"+ele)); //----9----19-----15----10
//便利集合元素:使用方法引用
newIntS.forEach(System.out::print); //919-1510
}

【聚集操作分类】

[ 中间方法 ]

中间操作允许流保持打开状态,并允许直接调用后续方法。上例中的map方法就是中间方法,中间方法的返回值是另外一个流。

[ 末端方法 ]

末端方法是对流的最终操作。当对某个Stream执行末端方法后,该流将会被"消耗",且不可再用。上例中的sum()、count().....大都是末端方法。

【流的方法的两个特征】

[ 有状态的方法 ]

这种方法会给流增加一些新的属性,比如元素的唯一性、元素的最大数量、保证元素以排序的方式被处理等。

有状态的方法一般会需要更大的性能开销。

[ 短路方法 ]

短路方法会尽早结束对流的操作,不必检查所有的元素。

【Stream常用的中间方法】

* filter(Predicate predicate):过滤Stream中不符合predicate的元素。即保留满足条件的元素。

* mapToXxx(ToXxxFunction mapper):使用ToXxxFunction对流中的元素执行一对一的转换,该方法返回的新流中包含了ToXxxFunction转换生成的所有元素。

* peek(Cosumer action):依次对每个元素执行一些操作,该方法返回的流与原有的流包含相同的元素。该方法常用于调试。

* distinct():该方法用于排序流中所有重复元素(判断元素重复的标准是使用equals()比较返回true)。这是一个有状态的方法。

* sorted():该方法用于保证流中的元素在后续的访问中处于有序状态。这是一个有状态的方法。

* limit(long maxSize):该方法用于保证对该流的后续访问中最大允许访问的元素个数。这是一个有状态、短路的方法。

【Stream常用的末端方法】

* forEach(Cosumer action):遍历流中的所有元素,对每个元素执行action。

* toArray():将流中的所有元素转换成一个数组。

* reduce():该方法有3个重载的版本,都用于通过某种操作来合并流中的元素。

* min():返回流中的所有元素的最小值。

* max():返回流中的所有元素的最大值。

* count():返回流中所有元素的数量。

* anyMatch(Predicate predicate):判断流中是否至少包含一个元素满足符合Predicate条件。

* allMatch(Predicate predicate):判断流中是否每个元素都符合Predicate条件。

* noneMatch(Predicate predicate):判断流中是否含有所有元素都不符合Predicate条件。

* findFirst():返回流中的第一个元素。

* findAny():返回流中的任意一个元素。

【使用Stream直接对集合中的元素进行批量操作】

public static void main(String[] args) {
Collection<String> books=new ArrayList<>();
books.add("《Java编程思想》");
books.add("《Java并发编程》");
books.add("《Java多线程实战》");
books.add("《Spring实战》");
books.add("《Spring技术内幕》");
books.add("《大话数据结构》");
books.add("《大话设计模式》");
books.add("《设计模式之禅》");
books.add("《我是一个长度很长长长长长长长长长长长长长长长长长长的书名》");
books.add("《我也是一个长度很长长长长长长长长长长长长长长长长长长的书名》"); //统计包含"Java"的书本数量
System.out.println(books.stream()
.filter(ele->((String)ele).contains("Java"))
.count()); //3
//统计以"《大话"开头的书本数量
System.out.println(books.stream()
.filter(ele->((String)ele).startsWith("《大话"))
.count()); //2
//统计输名字长度大于15的数量
System.out.println(books.stream()
.filter(ele->((String)ele).length()>)
.count()); //2
//先调用Collection对象的Stream()方法将集合转换成Stream对象
//再调用Stream对象的maptoInt()方法获取原有的Stream对应的IntStream
   //这里的mapToInt是一个中间方法,因此程序可以继续调用IntStream的forEach方法来遍历流中的数据
books.stream().mapToInt(ele->((String)ele).length())
.forEach(ele->System.out.print("--"+ele)); //--10--10--11--10--12--8--8--8--30--31
}

【运行结果】

09_Java8操作集合的一些新特性的更多相关文章

  1. jdk8中关于操作集合的一些新特性,遍历和排序操作

    jdk8增加了不少新的东西,在集合操作这块,就有如 lamda表达式,stream,sort,optional等新的类,主要涉及遍历和排序等方面,新特性提升了不少性能,我们开发就是要拥抱新事物,守着老 ...

  2. Java8新特性 1——利用流和Lambda表达式操作集合

    Java8中可以用简洁的代码来操作集合,比如List,Map,他们的实现ArrayList.以此来实现Java8的充分利用CPU的目标. 流和Lambda表达式都是Java8中的新特性.流可以实现对集 ...

  3. Java8 新特性之集合操作Stream

    Java8 新特性之集合操作Stream Stream简介 Java 8引入了全新的Stream API.这里的Stream和I/O流不同,它更像具有Iterable的集合类,但行为和集合类又有所不同 ...

  4. java8新特性,使用流遍历集合

    在这篇“Java 8新特性教程”系列文章中,我们会深入解释,并通过代码来展示,如何通过流来遍历集合,如何从集合和数组来创建流,以及怎么聚合流的值. 在之前的文章“遍历.过滤.处理集合及使用Lambda ...

  5. List集合及新特性引用

    ArrayList就是动态数组,也是一个对象. 创建一个ArrayList对象,该对象存放在堆内存中,且是一个内存连续的内存区域. 1.ArrayList是用数组实现的,这个数组的内存是连续的,不存在 ...

  6. JDK1.5新特性,基础类库篇,集合框架(Collections)

    集合框架在JDK1.5中增强特性如下: 一. 新语言特性的增强 泛型(Generics)- 增加了集合框架在编译时段的元素类型检查,节省了遍历元素时类型转换代码量. For-Loop循环(Enhanc ...

  7. Java 8新特性之旅:使用Stream API处理集合

    在这篇“Java 8新特性教程”系列文章中,我们会深入解释,并通过代码来展示,如何通过流来遍历集合,如何从集合和数组来创建流,以及怎么聚合流的值. 在之前的文章“遍历.过滤.处理集合及使用Lambda ...

  8. JavaSE----API之集合(Collection、List及其子类、Set及其子类、JDK1.5新特性)

    5.集合类 集合类的由来: 对象用于封装特有数据,对象多了须要存储:假设对象的个数不确定.就使用集合容器进行存储. 集合容器由于内部的数据结构不同,有多种详细容器.不断的向上抽取,就形成了集合框架. ...

  9. Java 8 新特性-Stream更优雅的处理集合入门

    Java 8 新特性之--Stream 一. 简单介绍 Stream是Java 8提出了的一种新的对集合对象功能的增强.它集合Lambda表达式,对集合提供了一些非常便利,高效的操作,使得代码具有非常 ...

随机推荐

  1. VS里面如何设置环境默认的开发语言

  2. Codeforces Round #280 (Div. 2) D. Vanya and Computer Game 二分

    D. Vanya and Computer Game Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contes ...

  3. 2015南阳CCPC H - Sudoku 暴力

    H - Sudoku Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 无 Description Yi Sima was one of the best cou ...

  4. Web APP 随笔

    自Iphone和Android这两个牛逼的手机操作系统发布以来,在互联网界从此就多了一个新的名词-WebApp(意为基于WEB形式的应用程序,运行在高端的移动终端设备). 开发者们都知道在高端智能手机 ...

  5. C/C++产生随机数

    <一> C/C++如何产生随机数:这里要用到的是rand()函数, srand()函数,C语言/C++里没有自带的random(int number)函数. (1)  假设你仅仅要产生随机 ...

  6. /proc/sysrq-trigger详解

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://itnihao.blog.51cto.com/1741976/830374 htt ...

  7. day05 Java基础

    1.数组初始化:为数组开辟内存空间,并为每个数组元素赋予值.数组初始化方式: 方式一:动态初始化:初始化时只指定数组长度,由系统为数组分配初始值. 格式:数组类型[] 数组名称=new 数组类型[数组 ...

  8. MongoDB笔记--安装篇

    安装MongoDB 第一步:下载安装包:官方下载地址←单击此处,如果是win系统,注意是64位还是32位版本的,请选择正确的版本. 第二步:新建目录“D:\MongoDB”,解压下载到的安装包,找到b ...

  9. C#并行编程 (Barrier,CountdownEvent,ManualResetEventSlim,SemaphoreSlim,SpinLock,SpinWait )

    背景 有时候必须访问变量.实例.方法.属性或者结构体,而这些并没有准备好用于并发访问,或者有时候需要执行部分代码,而这些代码必须单独运行,这是不得不通过将任务分解的方式让它们独立运行. 当任务和线程要 ...

  10. WORD神操作!第一个技巧你就傻眼了!

    原文:http://mp.weixin.qq.com/s?__biz=MzA4NzkyMDIwNw==&mid=220128483&idx=4&sn=cfa87c941f36f ...