前言:总之,中间操作只是创建另一个流,不会执行任何处理,直到最终操作被调用。一旦最终操作被调用,则开始遍历所有的流,并且相关的函数会逐一应用到流上。中间操作是惰性操作,所以,流支持惰性,下面是一些函数的分类。
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();
文章出自:http://qh.itpxw.cn/peixun/software/201841423.html
免责声明:本站文章均由入驻起航学习网的会员所发或者网络转载,所述观点仅代表作者本人,不代表起航学习网立场。如有侵权或者其他问题,请联系举报,必删。侵权投诉
IT培训网 访问该机构站点 报名留言 加为好友 用户等级:注册会员
用户级别:10
机构名称:IT培训网
联 系 人:罗老师
联系电话:13783581536
联系手机:13783581536
在线客服:
在 线 QQ:
电子邮件:
网站域名:http://www.itpxw.cn
注册时间:2016-07-18 11:07
最后登录:2024-02-20 13:02
Java定义方法的格式是什么?IT培训网小编来告诉大家。所谓方法...
大家在Java教程中会学到关于Java消息推送的知识,那么,Java消息...
常用的Java日期格式转换有哪些?IT培训网小编来告诉大家。 1...
Java创建对象数组的方法是什么?IT培训网小编来告诉大家。Ja...