流是Java8引入的一个新特性,提供了对集合元素一系列便捷的操做,能够用不多的代码实现复杂的功能。
流有两大类,分别是对象流(Stream),基本数据流(IntStream、LongStream、DoubleStream)。java
流的使用一般为三个步骤:①建立流 ②描述流 ③求值数组
经过Stream静态工厂方法来建立,Stream类提供了如下方法建立流。数据结构
建立好流以后,就能够描述流了。更准确的说法是,声明流的中间操做。
中间操做比较经常使用的有如下几种(返回值为Stream的均为中间操做)框架
与中间操做相对应的是终端操做,也就是咱们的第三步,求值。
经常使用的终端操做有如下几种(返回值不为Stream的为终端操做)dom
流是使用了内部迭代而不是外部迭代
内部迭代使用了惰性求值,只有在须要结果的那一刻才进行求值。
全部的中间操做(只描述流)都是惰性求值,由于只返回了Stream。
// 用户类函数
public class User { private Integer id; private String name; private Integer age; // GET SET Constructor .. }
// 初始化数据调试
List<User> userList = new ArrayList<User>() { /** */ private static final long serialVersionUID = 1L; { add(new User(1, "Luffy", 17)); add(new User(2, "Zoro", 19)); add(new User(3, "Nami", 18)); add(new User(4, "Usopp", 17)); add(new User(5, "Sanji", 19)); add(new User(6, "Chopper", 15)); add(new User(7, "Robin", 28)); add(new User(8, "FRANKY", 34)); add(new User(9, "BROOK", 88)); } };
// 例子code
@Test public void test1() { // 获取全部年龄大于17的用户 List<User> users = userList.stream() .filter(user -> user.getAge() > 17) .collect(Collectors.toList()); System.out.println(users); } // 静态导入Collectors后会更简洁。 // import static java.util.stream.Collectors.*; @Test public void test2() { // 根据年龄是否大于17岁对集合进行分块 Map<Boolean, List<User>> users = userList.stream() .collect(partitioningBy(u -> u.getAge() > 17)); System.out.println(users); } @Test public void test3() { // 按照年龄,将用户分组 Map<Integer, List<User>> users = userList.stream() .collect(groupingBy(User::getAge)); System.out.println(users); } @Test public void test4() { // 获取全部用户的名称 List<String> names = userList.stream() .map(User::getName) .collect(toList()); System.out.println(names); } @Test public void test5() { // 获取年龄最大的用户(只返回一个) User user = userList.stream() .max((u1, u2) -> { return u1.getAge() > u2.getAge() ? 1 : -1; }) .get(); System.out.println(user); } @Test public void test6() { // 获取用户年龄总和 int ageSum = userList.stream() .map(User::getAge) .reduce(0, (acc, element) -> { acc += element; return acc; }); System.out.println(ageSum); ageSum = userList.stream() .map(User::getAge) .reduce(0, Integer::sum); System.out.println(ageSum); ageSum = userList.stream() .collect(summingInt(User::getAge)); System.out.println(ageSum); } @Test public void test7() { // 获取组成用户姓名的字母 Set<String> set = userList.stream() .map(User::getName) .map(name -> name.split("")) .flatMap(Arrays::stream) .collect(toSet()); System.out.println(set); }
如何进行调试对象
// 能够利用peek查看流中的数据状态 userList.stream() .peek(System.out::println) .map(u -> u.getName()) .peek(System.out::println) .collect(toList());
使用并行仍是串行排序
// 将流改成并行流十分简单,只须要将stream方法改成parallelStream Map<Integer, List<User>> users = userList.parallelStream() .collect(groupingBy(User::getAge)); // 或是使用 parallel() 声明为并行 Stream.iterate(0L, i -> i + 1) .parallel() .limit(10) .reduce(0L, Long::sum);
Java8流的并行属于数据并行,即将数据分为几部分,利用多核CPU对每块数据执行运算,最终汇总数据,获得答案。底层是使用了fork/join框架,fork递归分解问题,而后每段并行执行,最终join合并结果。 所以,使用并行流须要考虑如下几点: