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 */