JDK8 Stream 从入门到装逼(三)
2016-09-07 13:07
302 查看
摘要: Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation)。Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。通常编写并行代码很难而且容易出错, 但使用 Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程
在lambdas中,可以看到lambda表达式让代码更加简洁、干净、容易理解,并允许不需要创建一个类就可以达到目的。lambdas很好的帮助开发人员更好的表达片段代码的意思,Stream对于集合提供一个抽象计算和Fluent接口更能让程序猿变得爽歪歪。
###1. 构建stream
初始化stream的几个方法
###2. 可以怎样用stream
执行结果:
上面的例子,大概了解stream的用法,下面分点介绍一下:
JDK8 collection中已经实现了一个default的stream方法
如果不了解predicate、function的用法,可以系列篇之函数式接口编程
###3. stream 懒加载
执行结果:
上述看到,map(x -> x/0)并没有执行,如果换成下面代码:
执行结果:
stream只有真正使用到的时候才去真正的执行。
###4. stream 链式编程什么时候才是结束
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
当steam遇上这些方法才算是结束,其他的方法,例如:
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
还是可以在上一个操作结果上继续操作,例如:根据条件filter -> sort -> map
###5. stream api 例子
####5.1 distinct 去重
####5.2 skip 跳过条数 limit 限定结果返回几条
####5.3 fitler 参数为:Predicate 过滤满足条件的结果, Count 统计条数
####5.4 flatMap 使数据扁平化处理
很多情景,我们都会用到一个类中有List<Object>属性,怎样转化成Strean<Object>呢,这是flatMap就该出手了
//执行结果:
####5.5 anyMatch
####5.6 reduce
Optional<T> reduce(BinaryOperator<T> accumulator) 这个方法的主要作用是把 Stream 元素组合起来,Optional使用方法,请参考网红篇:Java函数式开发——优雅的Optional空指针处理
执行结果:
####5.7 Parallel
并行运行 vs 普通stream操作
在lambdas中,可以看到lambda表达式让代码更加简洁、干净、容易理解,并允许不需要创建一个类就可以达到目的。lambdas很好的帮助开发人员更好的表达片段代码的意思,Stream对于集合提供一个抽象计算和Fluent接口更能让程序猿变得爽歪歪。
###1. 构建stream
初始化stream的几个方法
//1. Stream generate 生成无限个无序的stream Stream<String> stream = Stream.generate(() -> UUID.randomUUID().toString()); // 2. of 构造stream Stream<Integer> integerStream = Stream.of(1, 2, 4, 6, 3, 9, 7); //3.集合构造出stream Stream<List<Integer>> inputStream = Stream.of( Arrays.asList(1), Arrays.asList(2, 3), Arrays.asList(4, 5, 6) );
###2. 可以怎样用stream
/** * jdk8 stream 用法 * Created by kaishui on 2016/9/3. */ public class JDK_07StreamTest { static class User { private String name; private String password; public User(String name, String password) { this.name = name; this.password = password; } //省略getter and setter } public static void main(String[] args) { List<User> userList = new ArrayList<User>(); userList.add(new User("name1", "passowrd1")); userList.add(new User("name4321", "passowrd4")); userList.add(new User("name321", "passowrd3")); userList.add(new User("kaishui", "kaishuiPassword")); userList.add(new User("name21", "passowrd2")); //1. 在jdk7之前的代码中,也许我们经常会这样写 List<User> otherUsers = new ArrayList<>(); for (User u : userList) { //获取含有 "name"的User if (null != u.getName() && u.getName().indexOf("name") >= 0) { otherUsers.add(u); } } //按照名字长度排序 Collections.sort(otherUsers, new Comparator<User>() { @Override public int compare(User u1, User u2) { return u1.getName().length() - u2.getName().length(); } }); //打印 for (User u : otherUsers) { System.out.println(u.getName()); } System.out.println("-------我是一条分割线1---------"); System.out.println("-------jdk8 示例---------"); // 2. jdk8 使用stream操作集合 List<String> nameList = userList.stream() .filter(u -> null != u.getName() && u.getName().indexOf("name") >= 0) //过滤结果 .sorted((u1, u2) -> u1.getName().length() - u2.getName().length()) //排序 .map(u -> u.getName()) //提取 .collect(Collectors.toList()); //把上述步骤后的结果转换成list //打印 nameList.forEach(System.out::println); } }
执行结果:
name1 name21 name321 name4321 -------我是一条分割线1--------- -------jdk8--------- name1 name21 name321 name4321
上面的例子,大概了解stream的用法,下面分点介绍一下:
JDK8 collection中已经实现了一个default的stream方法
1. stream() 在集合collection中新建一个stream的管道,有点类似Linux命令中 grep or awk的用法。 2. filter(Predicate) 过滤条件, 看到Predicate应该可以想到就是过滤数据。 3. sorted(Comparator) 根据Comparator排序,英语国家的就是爽,写接口都可以省注释了. 4. map(Function) 提取计算,根据Funtion的作用,我们也知道,<T,R>输入一个T,返回一个R。 5. collect(Collectors.toList()) 把上述操作stream的结果转为另外一个集合。
如果不了解predicate、function的用法,可以系列篇之函数式接口编程
###3. stream 懒加载
// 1. of 构造 Stream<Integer> Stream<Integer> integerStream = Stream.of(1, 2, 4, 6, 3, 9, 7).map(x -> x / 0); System.out.println("-------我是一条分割线--------");
执行结果:
-------我是一条分割线--------
上述看到,map(x -> x/0)并没有执行,如果换成下面代码:
// 1. of 构造 Stream<Integer> Stream<Integer> integerStream = Stream.of(1, 2, 4, 6, 3, 9, 7).map(x -> x / 0); List<Integer> list = integerStream.collect(Collectors.toList()); System.out.println("-------我是一条分割线--------");
执行结果:
Exception in thread "main" java.lang.ArithmeticException: / by zero at com.iu.jdk8.JDK_09StreamLazyLoadTest.lambda$main$0(JDK_09StreamLazyLoadTest.java:19) at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) at com.iu.jdk8.JDK_09StreamLazyLoadTest.main(JDK_09StreamLazyLoadTest.java:20) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
stream只有真正使用到的时候才去真正的执行。
###4. stream 链式编程什么时候才是结束
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
当steam遇上这些方法才算是结束,其他的方法,例如:
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
还是可以在上一个操作结果上继续操作,例如:根据条件filter -> sort -> map
List<User> userList = new ArrayList<User>(); for (int i = 0; i < 10; i++) { userList.add(new User("name" + i, "passowrd" + i, i)); } List<String> nameList = userList.stream() .filter(u -> null != u.getName() && u.getName().indexOf("name") >= 0) //过滤结果 .sorted((u1, u2) -> u1.getName().length() - u2.getName().length()) //排序 .map(u -> u.getName()) //提取 .collect(Collectors.toList()); //把上述步骤后的结果转换成list
###5. stream api 例子
####5.1 distinct 去重
Stream.of(1, 2, 4, 6, 3, 9, 7, 2, 4, 9, 7).distinct().sorted().forEach(System.out::print); //执行结果: 1234679
####5.2 skip 跳过条数 limit 限定结果返回几条
Stream.of(1, 2, 4, 6, 3, 9, 7, 2, 4, 9, 7).skip(2).limit(3).forEach(System.out::print); //执行结果:463
####5.3 fitler 参数为:Predicate 过滤满足条件的结果, Count 统计条数
//获取集合中7的个数 long sum = Stream.of(1, 2, 4, 6, 3, 9, 7, 2, 4, 9, 7).filter(x -> x == 7).count(); System.out.println("sum = " + sum); //执行结果: sum = 2
####5.4 flatMap 使数据扁平化处理
很多情景,我们都会用到一个类中有List<Object>属性,怎样转化成Strean<Object>呢,这是flatMap就该出手了
public class JDK_08StreamFlatMapTest { static class User { private String name; private String password; private int no; public User(String name, String password, int no) { this.name = name; this.password = password; this.no = no; } //省略getter and setter } //班级 static class Clazz{ List<User> users; //省略getter and setter } public static void main(String[] args) { List<User> girlList = new ArrayList<User>(); List<User> boyList = new ArrayList<User>(); for (int i = 0; i < 10; i++) { girlList.add(new User("girl" + i, "passowrd" + i, i)); boyList.add(new User("boy" + i, "passowrd" + i, i)); } //班级1 Clazz clazz = new Clazz(); //班级2 Clazz clazz2 = new Clazz(); girlList.addAll(boyList); clazz.setUsers(girlList); clazz2.setUsers(girlList); //clazz stream Stream<Clazz> clazzSteam = Stream.of(clazz, clazz2); //clazz stream -> user stream 扁平化 Stream<User> allUserStream = clazzSteam.flatMap(c -> c.getUsers().stream()); System.out.println("两个班级一共多少人:" + allUserStream.count());; } }
//执行结果:
两个班级一共多少人:40
####5.5 anyMatch
//是否存在x*x = 81的结果 boolean flag = Stream.of(1, 2, 4, 6, 3, 9, 7, 2, 4, 9, 7).map(x -> x * x).anyMatch(x -> x == 81); System.out.println(flag); //执行结果:true
####5.6 reduce
Optional<T> reduce(BinaryOperator<T> accumulator) 这个方法的主要作用是把 Stream 元素组合起来,Optional使用方法,请参考网红篇:Java函数式开发——优雅的Optional空指针处理
//clazz stream -> user stream Stream<User> allUserStream = clazzSteam.flatMap(c -> c.getUsers().stream()); //串起所有名字 想了解optional用法可以参考:http://my.oschina.net/chkui/blog/739034 Optional<String> names = allUserStream. map(User::getName).sorted((first, second) -> first.compareTo(second)) .reduce((first, second) -> first + " *** " + second); System.out.println(names.get());
执行结果:
boy0 *** boy0 *** boy1 *** boy1 *** boy2 *** boy2 *** boy3 *** boy3 *** boy4 *** boy4 *** boy5 *** boy5 *** boy6 *** boy6 *** boy7 *** boy7 *** boy8 *** boy8 *** boy9 *** boy9 *** girl0 *** girl0 *** girl1 *** girl1 *** girl2 *** girl2 *** girl3 *** girl3 *** girl4 *** girl4 *** girl5 *** girl5 *** girl6 *** girl6 *** girl7 *** girl7 *** girl8 *** girl8 *** girl9 *** girl9
####5.7 Parallel
并行运行 vs 普通stream操作
long startTime = System.nanoTime(); Map<String, List<Integer>> numbersPerThread = IntStream.rangeClosed(1, 100000) .parallel() .boxed() .collect(Collectors.groupingBy(i -> Thread.currentThread().getName())); long runTime = System.nanoTime() - startTime; System.out.println("运行时间:" + String.valueOf(runTime)); //运行时间:159695489
long startTime = System.nanoTime(); Map<String, List<Integer>> numbersPerThread = IntStream.rangeClosed(1, 100000) .boxed() .collect(Collectors.groupingBy(i -> Thread.currentThread().getName())); long runTime = System.nanoTime() - startTime; System.out.println("运行时间:" + String.valueOf(runTime)); //运行时间:94576511
相关文章推荐
- Java8系列--Java Stream入门篇(流的创建)
- 【Java框架型项目从入门到装逼】第十四节 查询用户列表展现到页面
- Nodejs基础:stream模块入门介绍与使用
- java8从入门到精通2:强大的Stream
- Android零基础入门第12节:熟悉Android Studio界面,开始装逼卖萌
- 不装逼的比特币,区块链入门
- 大数据生态系统基础:Apache Kafka基础(四):最新kafka编程入门:Stream API
- 【Java框架型项目从入门到装逼】第十二节 项目分层
- [转]Java Stream API入门篇
- 【Java框架型项目从入门到装逼】第十五节 - jdbc模糊查询实现(附带详细调试过程)
- Java SE8 Lambda 基础入门---Stream
- JDK8- java.util.stream 库笔记
- JDK8新特性Lambda入门
- JAVA8 Stream API 入门
- 【Java框架型项目从入门到装逼】第八节 - 用EasyUI绘制主界面
- 第二十三讲 JDK8的foreach与Consumer接口、四大核心函数式接口、Stream接口、队列与栈
- JDK8的随笔(06)_Aggregate聚合操作之stream的抛砖引玉
- 【Java框架型项目从入门到装逼】第十三节 用户新增功能完结篇
- 【编译】StreamInsight应用调优入门(四)——解析StreamInsight应用程序内存消耗
- Jdk8 之Stream使用