文档章节

JDK8的集合流式的简易操作

文文1
 文文1
发布于 2018/11/30 15:57
字数 1885
阅读 3
收藏 0
JDK

需要Lambda表达式的原因主要有三个:

1. 更紧凑的代码

2. 通过提供额外的功能对方法的功能进行修改的能力

3. 更好地支持多核处理

更紧凑的代码

Lambda表达式以一种简洁的方式去实现仅有一个方法的Java类。

例如,如果代码中有大量的匿名内部类–诸如用于UI应用中的监听器与处理器实现,以及用于并发应用中的Callable与Runnable实现–在使用了Lambda表达式之后,将使代码变得非常短,且更易于理解。

修改方法的能力

有时,方法不具备我们想要的一些功能。例如,Collection接口中的contains()方法只有当传入的对象确实存在于该集合对象中时才会返回true。但我们无法去干预该方法的功能,比如,若使用不同的大小写方案也可以认为正在查找的字符串存在于这个集合对象中,我们希望此时contains()方法也能返回true。

简单点儿说,我们所期望做的就是”将我们自己的新代码传入”已有的方法中,然后再调用这个传进去的代码。Lambda表达式提供了一种很好的途径来代表这种被传入已有方法且应该还会被回调的代码。

更好地支持多核处理

当今的CPU具备多个内核。这就意味着,多线程程序能够真正地被并行执行,这完全不同于在单核CPU中使用时间共享这种方式。通过在Java中支持函数式编程语法,Lambda表达式能帮助你编写简单的代码去高效地应用这些CPU内核。

例如,你能够并行地操控大集合对象,通过利用并行编程模式,如过滤、映射和化简(后面将会很快接触到这些模式),就可使用到CPU中所有可用的硬件线程。

一. 基本概念
1.1 为什么加入 集合的流式操作     
        JDK8 的Stream 是一个受到 函数式编程 和 多核时代影响而产生的东西。很多时候我们需要到底层返回数据,上层再对数据进行遍历,进行一些数据统计,但是之前的Java API 中很少有这种方法,这就需要我们自己来 Iterator 来遍历,如果JDK 能够为我们提供一些这种方法,并且能够为我们优化就好了。
         所以JDK8加入 了 java.util.stream包,实现了集合的流式操作,流式操作包括集合的过滤,排序,映射等功能。根据流的操作性,又可以分为 串行流 和 并行流。根据操作返回的结果不同,流式操作又分为中间操作和最终操作。大大方便了我们对于集合的操作。
最终操作:返回一特定类型的结果。
中间操作:返回流本身。
1.2 什么是 流
        Stream 不是 集合元素,也不是数据结构,它相当于一个 高级版本的 Iterator,不可以重复遍历里面的数据,像水一样,流过了就一去不复返。它和普通的 Iterator 不同的是,它可以并行遍历,普通的 Iterator 只能是串行,在一个线程中执行。

二. 串行流和并行流:
        串行流操作在一个线程中依次完成。并行流在多个线程中完成,主要利用了 JDK7 的 Fork/Join 框架来拆分任务和加速处理。相比串行流,并行流可以很大程度提高程序的效率。

三. 中间操作 和 最终操作        
中间操作:
filter(): 对元素进行过滤
sorted():对元素排序
map():元素映射
distinct():去除重复的元素
最终操作:
forEach():遍历每个元素。
reduce():把Stream 元素组合起来。例如,字符串拼接,数值的 sum,min,max ,average 都是特殊的 reduce。
collect():返回一个新的集合。
min():找到最小值。
max():找到最大值。

3.1 filter() 对元素进行过滤
Demo(有一链表,{1,2,3,4,5},把偶数过滤掉):

public class Test {  
    public static void main(String[] args) throws InterruptedException {  
        List list = new ArrayList();  
        for(int i = 1 ; i <= 5; ++i){  
            list.add(i);  
        }  
        list.stream().filter(param -> (int)param % 2 == 1)  
                    .forEach(System.out::println);  
    }  
}  


输出:

1  
3  
5  

3.2 sorted() 对元素进行排序
Demo(有一链表,{2,3,1,5,4},从小到大排序):

public class Test {  
    public static void main(String[] args) throws InterruptedException {  
        List list = new ArrayList();  
        list.add(2);  
        list.add(3);  
        list.add(1);  
        list.add(5);  
        list.add(4);  
        list.stream().sorted().forEach(System.out::println);  
    }  
}  


输出:

1  
2  
3  
4  
5  



Ps1: 此时为升序,那么有时候我们可能会需要到降序,此时做法可以如下:
        流除了提供默认的升序 sorted() 方法,也提供了:    

Stream<T> sorted(Comparator<? super T> comparator);  

那么,自定义比较函数即可,如下代码:

public class Test {  
    public static void main(String[] args) throws InterruptedException {  
        List list = new ArrayList();  
        list.add(2);  
        list.add(3);  
        list.add(1);  
        list.add(5);  
        list.add(4);  
//      list.stream().sorted().forEach(System.out::println);  
        list.stream().sorted( (param1,param2) -> ((int)param1 < (int)param2 ? 1 : -1 ) )  
                .forEach(System.out::println);  
    }  
}  


输出为:

5  
4  
3  
2  
1  


3.3 map() 元素映射
        也就是说,原来的链表的每个元素可以按照规则变成相应的元素。
Demo(链表 (1,0),变成 true,false):

public class Test {  
    public static void main(String[] args) throws InterruptedException {  
        List list = new ArrayList();  
        list.add(1);  
        list.add(0);  
        list.stream().map( param -> (int)param == 1 ? true:false )  
                .forEach(System.out::println);  
    }  
}  


输出:

true  
false  


3.4  distinct() 去除重复元素
Demo:

public class Test {  
    public static void main(String[] args) throws InterruptedException {  
        List list = new ArrayList();  
        list.add(1);  
        list.add(1);  
        list.add(0);  
        list.stream().distinct().forEach(System.out::println);  
    }  
}  


3.5 reduce() :把Stream 元素组合起来。
Demo(从1加到5):

public class Test {  
    public static void main(String[] args) throws InterruptedException {  
        List list = new ArrayList();  
        list.add(1);  
        list.add(2);  
        list.add(3);  
        list.add(4);  
        list.add(5);  
        System.out.println(  
                list.stream().reduce((param1,param2) ->(int)param1 + (int)param2 ).get());  
    }  
}  

注意,reduce() 返回一个 Optional 类型的对象,可以通过 get() 方法获得值。

3.6 collect() :返回一个新的集合
Demo(先把 list 集合的 奇数去掉,然后把剩下的偶数返回到 _list 集合中):

public class Test {  
    public static void main(String[] args) throws InterruptedException {  
        List list = new ArrayList();  
        list.add(1);  
        list.add(2);  
        list.add(3);  
        list.add(4);  
        list.add(5);  
          
        List _list = (List) list.stream().filter((param) -> (int)param % 2 == 0)  
                        .collect(Collectors.toList());  
        _list.forEach(System.out::println);  
    }  
}  


输出:

2  
4  


3.7 min(),max()  找到最大值最小值

public class Test {  
    public static void main(String[] args) throws InterruptedException {  
        List list = new ArrayList();  
        list.add(1);  
        list.add(2);  
        list.add(3);  
        list.add(4);  
        list.add(5);  
          
        System.out.println(list.stream().min(  
                (param1,param2) -> (int)param1 > (int)param2 ? 1:-1 ).get());  
        System.out.println(list.stream().max(  
                (param1,param2) -> (int)param1 > (int)param2 ? 1:-1 ).get());  
    }  
}  


        注意, min(),max() 方法也是返回 Optional 对象, 可以通过 get() 方法返回值。
        
总结:
1. 流式操作的引入:提高执行效率(并行),方便编码(有很多API 可用),提高可读性。
2. 流的分类:可以分为串行流和并行流;对于操作:可以分为中间操作和最终操作
3. 流API:
        中间操作:
                filter(): 对元素进行过滤;
                sorted():对元素排序;
                map():元素映射;
                distinct():去除重复的元素 。
        最终操作:
                forEach():遍历每个元素;
                reduce():把Stream 元素组合起来。例如,字符串拼接,数值的 sum,min,max ,average 都是特殊的 reduce。
                collect():返回一个新的集合。
                min():找到最小值。
                max():找到最大值。
 

本文转载自:https://blog.csdn.net/asdfsadfasdfsa/article/details/55654629 

共有 人打赏支持
文文1
粉丝 23
博文 391
码字总数 124158
作品 0
长沙
程序员
私信 提问
JDK8新特性之Lambda表达式

什么是Lambda表达式 Java 8的一个大亮点是引入Lambda表达式,使用它设计的代码会更加简洁。当开发者在编写Lambda表达式时,也会随之被编译成一个函数式接口。 Lambda语法 一行执行语句的写法...

java技术栈
2017/10/05
0
0
使用JDK8新特性重构你的代码

lambda 表达式 当一个接口只有一个方法的时候都可以使用lambda 表达式代替 这种称为函数接口可以用 @FunctionalInterface 修饰 lambda 表达式多种形式 使用lambda表达式实现设计模式 这里我们...

12叔
2016/04/15
477
0
深入理解Java8 Lambda表达式

一、Lambda表达式是什么? Lambda表达式有两个特点:一是匿名函数;二是可传递。 匿名函数的应用场景是: 通常在需要一个函数,但又不想费神去命名一个函数的场合下使用。Lambda表达式所表示...

微笑向暖wx
2018/12/18
0
0
Java 8开发的4大顶级技巧

我使用Java 8编码已经有些年头,既用于新的应用程序,也用来迁移现有的应用,感觉是时候写一些我发现的非常有用的“最佳实践”。 我个人并不喜欢“最佳实践”这个说法,因为它意味着“一刀切...

架构师springboot
01/14
0
0
jdk10中stream流里面peek方法注意点

最近在我的课程里面SpringBoot2.0不容错过的新特性 WebFlux响应式编程里面,有学员提出了以下问题,在jdk10里面代码没有执行(课程中stream流是用jdk8演示的) 代码: public class LambdaD...

晓风轻
2018/06/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

winscp中使用sudo的方法

用截图了解如何在 WinSCP 中使用 sudo。 首先你需要检查你尝试使用 WinSCP 连接的 sftp 服务器的二进制文件的位置。 你可以使用以下命令检查 SFTP 服务器二进制文件位置: [root@kerneltalk...

Linux就该这么学
21分钟前
1
0
四、MyBatis中查询执行流程

一、查询执行大致流程 在MyBatis中,查询执行的大致流程如下:

yangjianzhou
27分钟前
1
0
系统幂等设计

前言 幂等简单的定义: 系统中的多次操作,不管多少次,都应该产生一样的效果,或返回一样的效果。 比如实际的业务请求为创建一个活动,理论上需要根据业务形态开发幂等创建活动的接口,这样...

春哥大魔王的博客
52分钟前
2
0
DevSecOps 运维模式中的安全性

导读 本文想从技术的角度谈谈我对云计算数据中心 DevSecOps 运维模式中的安全性的理解,和过去几年我在云服务业务连续性管理方面的探索。 现在公有云服务商都不约而同地转向 DevSecOps 模式。...

问题终结者
54分钟前
0
0
java 基础脑图 转载来的

NotFound403
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部