起航学习网 - 让每个人都能学到最前沿新知识、新技能!

起航学习网

当前位置: 起航学习网 > 短期培训 > 编程语言 > 零基础java编程进阶-Stream之函数式编程

零基础java编程进阶-Stream之函数式编程

时间:2018-07-12 14:34:53来源:编程网 作者:IT培训网 已有: 名学员访问该课程

前言:总之,中间操作只是创建另一个流,不会执行任何处理,直到最终操作被调用。一旦最终操作被调用,则开始遍历所有的流,并且相关的函数会逐一应用到流上。中间操作是惰性操作,所以,流支持惰性,下面是一些函数的分类。

Java 8编程进阶-Stream之函数式编程,怎么样学好java开发呢,很多人在学习java开发的路上遇到了重重难关,可见学习java不容易,想要成为java编程高手,更是难上加难!

1、什么是Stream

Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

总之,中间操作只是创建另一个流,不会执行任何处理,直到最终操作被调用。一旦最终操作被调用,则开始遍历所有的流,并且相关的函数会逐一应用到流上。中间操作是惰性操作,所以,流支持惰性,下面是一些函数的分类。

Stream操作分类

中间操作(Intermediate operations)

无状态(Stateless)

unordered() filter() map() mapToInt() mapToLong() mapToDouble()   flatMap() flatMapToInt() flatMapToLong() flatMapToDouble() peek()

有状态(Stateful)

distinct() sorted() sorted() limit() skip()

最终操作(Terminal operations)

非短路操作

forEach() forEachOrdered() toArray() reduce() collect() max()   min() count()

短路操作(short-circuiting)

anyMatch() allMatch() noneMatch() findFirst() findAny()

2、流的使用

2.1、获取Stream

在使用流之前,首先需要拥有一个数据源,并通过StreamAPI提供的一些方法获取该数据源的流对象。数据源可以有多种形式:

(1)集合 
这种数据源较为常用,通过stream()方法即可获取流对象:

List<String> list = new ArrayList<>();   Stream<String> stream = list.stream();

(2)数组 
通过Arrays类提供的静态函数stream()获取数组的流对象:

String[] array = {"a","b","c"};   Stream<String> stream = Arrays.stream(array);

(3)值 
直接将几个值变成流对象:

Stream<String> stream = Stream.of("a", "b", "c");

2.2、forEach

对流中的每个元素执行一些操作。

List<String> list = new ArrayList<>(Arrays.asList("a","b","c"));    //写法一    list.stream().forEach(x -> {        System.out.println(x);    });    //写法二    list.stream().forEach(System.out::println);

2.3、map

接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素

List<String> list = new ArrayList<>(Arrays.asList("a","b","c"));    //写法一    list.stream().forEach(x -> {        System.out.println(x);    });    //写法二    list.stream().forEach(System.out::println);

2.4、flatMap

接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。

List<String> list = new ArrayList<>(Arrays.asList("a,1","b,2","c,3"));    List<String> newList = list.stream().flatMap(x->{        String[] array = x.split(",");        return Arrays.stream(array);    }).collect(Collectors.toList());

结果:

[a, 1, b, 2, c, 3]

2.5、reduce()

通过一个二进制操作将流中的元素合并到一起。

List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));    //写法一,累加不带初始值    Optional accResult = list.stream().reduce((acc, item) -> {        acc += item;        return acc;    });

输出6

//写法一,累加带初始值10    int result1 = list.stream().reduce(10, (acc, item) -> {        acc += item;        return acc;    });

输出16

2.6、filter()

过滤元素

List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3,4));    List<Integer> newList = list.stream().filter(x -> x >=3).collect(Collectors.toList());

输出[3,4]

2.7、distinct()

去除重复元素

List<Integer> list = new ArrayList<>(Arrays.asList(1, 1, 1,2,2));    List<Integer> newList = list.stream().distinct().collect(Collectors.toList());

输出结果

[1,2]

2.8、collect() 

将流中的元素倾倒入某些容器

(1)toList

将元素转成List,很简单,上面的实例很多

(2)toSet

将元素转成Set

List<Integer> list = new ArrayList<>(Arrays.asList(1, 1, 1, 2, 2));    Set<Integer> set = list.stream().collect(Collectors.toSet());

(3) toMap

将元素转成Map

用法可以如下

public Map<Long, String> getIdNameMap(List<Account> accounts) {return accounts.stream().collect(Collectors.toMap(Account::getId, Account::getUsername));}

收集成实体本身map

代码如下:

public Map<Long, Account> getIdAccountMap(List<Account> accounts) {return accounts.stream().collect(Collectors.toMap(Account::getId, account -> account));}

account -> account是一个返回本身的lambda表达式,其实还可以使用Function接口中的一个默认方法代替,使整个方法更简洁优雅:

public Map<Long, Account> getIdAccountMap(List<Account> accounts) {return accounts.stream().collect(Collectors.toMap(Account::getId, Function.identity()));}

重复key的情况

代码如下:

public Map<String, Account> getNameAccountMap(List<Account> accounts) {return accounts.stream().collect(Collectors.toMap(Account::getUsername, Function.identity()));}

这个方法可能报错(java.lang.IllegalStateException: Duplicate key),因为name是有可能重复的。toMap有个重载方法,可以传入一个合并的函数来解决key冲突问题:

public Map<String, Account> getNameAccountMap(List<Account> accounts) {return accounts.stream().collect(Collectors.toMap(Account::getUsername, Function.identity(), (key1, key2) -> key2));}

这里只是简单的使用后者覆盖前者来解决key重复问题。

指定具体收集的map

toMap还有另一个重载方法,可以指定一个Map的具体实现,来收集数据:

public Map<String, Account> getNameAccountMap(List<Account> accounts) {return accounts.stream().collect(Collectors.toMap(Account::getUsername, Function.identity(), (key1, key2) -> key2, LinkedHashMap::new));}

2.8、min()  
根据一个比较器找到流中元素的最小值。

BigDecimal min = planList.stream().min((a,b)->a.getPrice().compareTo(b.getPrice())).get().getPrice();

2.9、max() 

根据一个比较器找到流中元素的最大值。

BigDecimal max = planList.stream().max((a,b)->a.getPrice().compareTo(b.getPrice())).get().getPrice();

2.10、count() 

计算流中元素的数量。

List<Integer> list = new ArrayList<>(Arrays.asList(14, 23, 3,10, 1,6));    long min = list.stream().distinct().count();
 (责任编辑:IT培训网)
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------

原文标题:零基础java编程进阶-Stream之函数式编程

原文链接:http://www.epx365.cn/peixun/software/201841423.html

------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
培训学校
IT培训网 访问该机构站点 报名留言 加为好友 用户等级:注册会员 用户级别:10 机构名称:IT培训网 联 系 人:王老师 联系电话:0371-55025032 联系手机:13783581536 在线客服:起航学习网客服 在 线 QQ:起航学习网客服 电子邮件:3158895217@qq.com 网站域名:http://www.cnitedu.cn 注册时间:2016-07-18 11:07 最后登录:2018-07-12 13:07