1 User模型
public class User { private String address; private String name; private Integer age; public User(String address, String name, Integer age) { this.address = address; this.name = name; this.age = age; } ...... @Override public String toString() { return "User [address=" + address + ", name=" + name + ", age=" + age + "]"; } }
2 获取Stream
2.1 通过of方法
User user1 = new User("上海", "甲", 17); User user2 = new User("上海", "乙", 19); User user3 = new User("北京", "丙", 20); User user4 = new User("北京", "丁", 18); Stream<User> stream = Stream.of(user1, user2, user3, user4);
2.2 通过Collection
List<User> list = new ArrayList<>(); Stream<User> stream = list.stream();
2.3 如何消费多次Stream?
提示:使用stream只能消费一次,否则报错:stream has already been operated upon or closed。
//第一次使用 stream stream.map(user -> user.getName()).collect(Collectors.toList()); //第二次使用 stream 会报错。 stream.map(user -> user.getName()).collect(Collectors.toSet()); //解决办法 Supplier<Stream<User>> streamSupplier = () -> Stream.of(user1, user2, user3, user4); streamSupplier.get().map(user -> user.getName()).collect(Collectors.toList()); streamSupplier.get().map(user -> user.getName()).collect(Collectors.toSet());
3 常用
Supplier<Stream<User>> streamSupplier = () -> Stream.of(user1, user2, user3, user4); // 转list List<String> names = streamSupplier.get().map(user -> user.getName()).collect(Collectors.toList()); // 转set Set<String> address = streamSupplier.get().map(user -> user.getName()).collect(Collectors.toSet()); // 转map,需要指定key和value,Function.identity()表示当前的User对象本身(转map很常用) Map<String, User> map = streamSupplier.get().collect(Collectors.toMap(user -> user.getName(), Function.identity())); // 计算元素中的个数 Long count = streamSupplier.get().collect(Collectors.counting()); List<String> strs = Arrays.asList("a", "a", "a", "a", "b"); //只要有一个 a,就为 true,下面返回:TRUE boolean anyMatch = strs.stream().anyMatch(str -> str.equals("a")); //都是 a,就为 true,下面返回:FALSE boolean allMatch = strs.stream().allMatch(str -> str.equals("a")); //都不是 a,就为 true,下面返回:FALSE boolean noneMatch = strs.stream().noneMatch(str -> str.equals("a")); // 数据求和 summingInt summingLong,summingDouble Integer sumAges = streamSupplier.get().collect(Collectors.summingInt(User::getAge)); // 平均值 averagingInt,averagingDouble,averagingLong Double aveAges = streamSupplier.get().collect(Collectors.averagingInt(User::getAge)); // 综合处理的,求最大值,最小值,平均值,求和操作 // summarizingInt,summarizingLong,summarizingDouble IntSummaryStatistics intSummary = streamSupplier.get().collect(Collectors.summarizingInt(User::getAge)); System.out.println(intSummary.getAverage()); //25.0 System.out.println(intSummary.getMax()); //40 System.out.println(intSummary.getMin()); //10 System.out.println(intSummary.getSum()); //100 // 连接字符串,当然也可以使用重载的方法,加上一些前缀,后缀和中间分隔符 String str1 = streamSupplier.get().map(user -> user.getName()).collect(Collectors.joining()); String str2 = streamSupplier.get().map(user -> user.getName()).collect(Collectors.joining(",")); String str3 = streamSupplier.get().map(user -> user.getName()).collect(Collectors.joining(",", "<", ">")); System.out.println(str1); //甲乙丙丁 System.out.println(str2); //甲,乙,丙,丁 System.out.println(str3); //<甲,乙,丙,丁> // maxBy 按照比较器中的比较结果刷选 // 最大值 Optional<Integer> maxAge = streamSupplier.get().map(user -> user.getAge()).collect(Collectors.maxBy(Comparator.comparingInt(age -> age))); // 最小值 Optional<Integer> minAge = streamSupplier.get().map(user -> user.getAge()).collect(Collectors.minBy(Comparator.comparingInt(age -> age))); // 归约操作 Optional<Integer> sumAge1 = streamSupplier.get().map(user -> user.getAge()).collect(Collectors.reducing((x, y) -> x + y)); //100 Object sumAge2 = streamSupplier.get().map(user -> user.getAge()).collect(Collectors.reducing(2, (x, y) -> x + y)); //102 // partitioningBy 分区操作(将大于30和小于等于30的分开) Map<Boolean, List<User>> partitioningMap = streamSupplier.get() .collect(Collectors.partitioningBy(user -> user.getAge() > 30));
4 group方法
4.1 按地址分组
Map<String, List<User>> userGroups = Stream.of(user1, user2, user3, user4) .collect(Collectors.groupingBy(user -> user.getAddress())); Iterator it = userGroups.entrySet().iterator(); while (it.hasNext()) { Map.Entry<Integer, List<User>> entry = (Map.Entry) it.next(); System.out.println("组名称 " + entry.getKey() + " = " + entry.getValue().size() + "条"); for (User user : entry.getValue()) { System.out.println(" " + user.getName()); } } /* 输出: 组名称 上海 = 2条 甲 乙 组名称 北京 = 2条 丙 丁 */
4.2 按地址分组,并返回每组年龄最大的User
Map<String, User> maxUserGroups = Stream.of(user1, user2, user3, user4) .collect(Collectors.groupingBy(user -> user.getAddress(), Collectors.collectingAndThen( Collectors.maxBy(Comparator.comparingLong(user -> user.getAge())), Optional::get) )); Iterator it = maxUserGroups.entrySet().iterator(); while (it.hasNext()) { Map.Entry<Integer, User> entry = (Map.Entry) it.next(); System.out.println("组名称:" + entry.getKey()); System.out.println("本组最大年龄用户:" + entry.getValue()); } /* 输出: 组名称:上海 本组最大年龄用户:User [address=上海, name=乙, age=19] 组名称:北京 本组最大年龄用户:User [address=北京, name=丙, age=20] */
5 排序
// 一、sorted() 默认使用自然序排序, 其中的元素必须实现Comparable 接口 Supplier<Stream<String>> stringListSupplier = () -> Stream.of("a", "e", "c", "d", "b"); // 自然序排序一个list stringListSupplier.get().sorted(); // 自然序逆序元素,使用Comparator 提供的reverseOrder() 方法 stringListSupplier.get().sorted(Comparator.reverseOrder()); // 二、sorted(Comparator<? super T> comparator) :我们可以使用lambada 来创建一个Comparator 实例。可以按照升序或着降序来排序元素。 User user1 = new User("上海", "甲", 17); User user2 = new User("上海", "乙", 19); User user3 = new User("北京", "丙", 20); User user4 = new User("北京", "丁", 18); Supplier<Stream<User>> supplier = () -> Stream.of(user1, user2, user3, user4); //User没有实现Comparable 接口,但可以使用Comparator 来排序 supplier.get().sorted(Comparator.comparing(User::getAge)); supplier.get().sorted(Comparator.comparing(User::getAge).reversed());
6 生成一个无限长度的Stream
6.1 使用 generate()
// 方式一 Stream.generate(() -> Math.random()); // 方式二 Stream.generate(Math::random); // 方式三 Stream.generate(new Supplier<Double>() { @Override public Double get() { return Math.random(); } }); // 一般这种无限长度的Stream都会配合Stream的limit()方法来用,否则会一直打印下去 Stream.generate(() -> Math.random()).limit(3).forEach(c -> System.out.println(c));
6.2 使用 iterate()
// 给定一个 seed,然后无限循环 Stream.iterate(1, num -> num + 1).limit(3).forEach(System.out::println); /* 输出结果: 1 2 3 */