1、stream创建
1.1、集合转stream
List<User> list = new ArrayList<>();
Stream<User> stream = list.stream();
Stream<User> parallelStream = list.parallelStream();
1.2、数组转stream
数组不能转并行流
int[] array = {1, 2, 3, 4, 5};
IntStream intStream = Arrays.stream(array);
Arrays.stream(array);
1.3、用Stream中静态方法创建
1.3.1、Stream.of
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
1.3.2、Stream.iterate: 以seed为起始值,根据UnaryOperator中返回值不断迭代
Stream<Integer> stream2 = Stream
.iterate(7, new UnaryOperator<Integer>() {
@Override
public Integer apply(Integer integer) {
return integer + 3;
}
})
.limit(4);
//7,10,13,16
stream2.forEach(System.out::println);
1.3.3、Stream.generate()不断获取Supplier中 get()方法返回值
Stream<Double> stream3 = Stream.generate(new Supplier<Double>() {
@Override
public Double get() {
return Math.random();
}
}).limit(3);
//0.014464768543508866 ,0.07501969315371027 ,0.2563750250586957
stream3.forEach(System.out::println);
1.4、使用 BufferedReader.lines() 方法,将每行内容转成流
BufferedReader reader = new BufferedReader(new FileReader("F:\\test_stream.txt"));
Stream<String> lineStream = reader.lines();
lineStream.forEach(System.out::println);
1.5、使用 Pattern.splitAsStream() 方法,将字符串分隔成流
Pattern pattern = Pattern.compile(",");
Stream<String> stringStream = pattern.splitAsStream("a,b,c,d");
stringStream.forEach(System.out::println);
2、中间操作符
2.1、筛选与切片
- filter:过滤:筛选出符合条件的元素,返回一个新的stream
- skip:跳过几个元素
- limit:取出几个元素 skip 和 limit 可搭配出数据库分页效果
- distinct:去重,通过流中元素的 hashCode() 和 equals() 去除重复元素
2.2、映射
- map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
- flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。
2.3、排序
- sorted():自然排序,流中元素需实现Comparable接口
- sorted(Comparator com):定制排序,自定义Comparator排序器
2.4、消费
peek:如同于map,能得到流中的每一个元素。但map接收的是一个Function表达式,有返回值;而peek接收的是Consumer表达式,没有返回值。
3、终止操作符
3.1、匹配、聚合操作
- allMatch:所有元素都满足条件则返回true,否则返回false
- noneMatch:所有元素都不满足条件则返回true,否则返回false
- anyMatch:只要有一个元素满足条件就返回true,都不满足条件则返回false
- findFirst:返回流中第一个元素
- findAny:返回流中的任意元素(串行流一般会返回第一个元素,并行流才有效果)
- count:返回流中元素的总个数
- max:返回流中元素最大值
- min:返回流中元素最小值
- reduce:规约,也称缩减,顾名思义,是把一个流缩减成一个值,能实现对集合求和、求乘积和求最值操作。
Optional<User> reduce = stream.reduce(new BinaryOperator<User>() {
@Override
public User apply(User user, User user2) {
//第一次:user为流中第一个元素,user2为流中第二个元素
//第二次:user为第一次apply返回的元素,user2为流中第三个元素
//第三次:user为第二次apply返回的元素,user2为流中第四个元素
//以此类推,并行流的顺序没有规律,但是最终的结果和串行流的结果是一样的
System.out.println("user = " + user.name + " user2 = " + user2.name);
return new User(user.name + user2.name, 1, 100);
}
});
System.out.println(reduce);
User identity = new User("曹操", 1, 50);
User user = stream.reduce(identity, new BinaryOperator<User>() {
@Override
public User apply(User user, User user2) {
//串行流:
//第一次:user为identity,user2为流中第一个元素
//第二次:user为第一次apply返回的元素,user2为流中第二个元素
//第三次:user为第二次apply返回的元素,user2为流中第三个元素
//以此类推。。。
// 并行流
//首先会用 identity 与 流中所有元素规约一次,即user = identity ,user2 为流中任意元素
//然后用上次规约出来的结果再次两两规约,以此类推。。。
System.out.println(Thread.currentThread().getName()+" user = " + user.name + " user2 = " + user2.name);
return new User(user.name + user2.name, 1, 100);
}
});
System.out.println(user);
User identity = new User("曹操", 1, 50);
User user = stream.reduce(identity,
new BiFunction<User, User, User>() {
@Override
public User apply(User user, User user2) {
System.out.println(Thread.currentThread().getName() + " BiFunction user = " + user.name + " user2 = " + user2.name);
return new User("BiFunction" + user.name + user2.name, 1, 100);
}
},
new BinaryOperator<User>() {
@Override
public User apply(User user, User user2) {
//串行流中该方法不会被回调,只会回调BiFunction中的apply方法,结果和2形参的reduce方法一样
//并行流
//首先在BiFunction中将identity与流中元素逐一规约,生成一个新的流
//然后将新的流在BinaryOperator中两两规约
System.out.println(Thread.currentThread().getName() + " BinaryOperator user = " + user.name + " user2 = " + user2.name);
return new User("BinaryOperator" + user.name + user2.name, 1, 100);
}
});
System.out.println(user);
4、收集(collect)
4.1、归集
- toList、toSet、toCollection、toMap、toConcurrentMap
List<User> toList = stream.collect(Collectors.toList());
Set<User> toSet = stream.collect(Collectors.toSet());
ArrayList<User> toCollection = stream.collect(Collectors.toCollection(ArrayList::new));
HashMap<String, User> toMap = stream.collect(Collectors.toMap(
user -> user.name,//第一个函数时接口返回的是map 的key
user -> user,//第二个函数时接口返回的是map 的value
(user, user2) -> user2,//两个元素键值对冲突时的解决方案
HashMap::new
));
//并行的,形参和toMap一样一样的
ConcurrentMap<String, User> concurrentMap = stream.collect(Collectors.toConcurrentMap(
user -> user.name,
user -> user,
(user, user2) -> user2,
ConcurrentHashMap::new
)
);
4.2、数据统计
Collectors提供了一系列用于数据统计的静态方法:
- 计数:count
- 平均值:averagingInt、averagingLong、averagingDouble
- 最值:maxBy、minBy
- 求和:summingInt、summingLong、summingDouble
- 统计以上所有:summarizingInt、summarizingLong、summarizingDouble
@Test
public void count() {
List<User> list = new ArrayList<>();
list.add(new User("吕布", 1, 48));
list.add(new User("貂蝉", 2, 37));
list.add(new User("刘备", 1, 56));
list.add(new User("孙尚香", 2, 18));
list.add(new User("周瑜", 2, 27));
list.add(new User("小乔", 2, 22));
// 统计数量,等效于list.stream().count(); 或list.size();
Long count = list.stream().collect(Collectors.counting());
// 求平均值
Double average = list.stream().collect(Collectors.averagingDouble(user -> user.age));
// 求最大值,等效于 list.stream().map(user -> user.age).max(Integer::compare);
Optional<Integer> max = list.stream().map(user -> user.age).collect(Collectors.maxBy(Integer::compare));
// 求和,等效于list.stream().mapToInt(user -> user.age).sum();
Integer sum = list.stream().collect(Collectors.summingInt(user -> user.age));
// 一次性统计所有信息
DoubleSummaryStatistics collect = list.stream().collect(Collectors.summarizingDouble(user -> user.age));
System.out.println("总数:" + count);//总数:6
System.out.println("平均值:" + average);//平均值:34.666666666666664
System.out.println("求和:" + sum);//求和:208
System.out.println("所有统计:" + collect);//所有统计:DoubleSummaryStatistics{count=6, sum=208.000000, min=18.000000, average=34.666667, max=56.000000}
}
4.3、分组分区
- partitioningBy:分区,分成两块区域,一块是满足条件的,一块不满足条件
- groupingBy:分组,按指定字段分组,该字段值相同的为元素都会分在一组
@Test
public void group() {
List<User> list = new ArrayList<>();
list.add(new User("诸葛亮", 1, 48, "法师"));
list.add(new User("貂蝉", 2, 37, "法师"));
list.add(new User("鲁班", 1, 56, "射手"));
list.add(new User("刘禅", 1, 18, "辅助"));
list.add(new User("韩信", 1, 27, "打野"));
list.add(new User("孙尚香", 2, 22, "射手"));
//{辅助=[User{name='刘禅', sex=1, age=18}], 打野=[User{name='韩信', sex=1, age=27}], 射手=[User{name='鲁班', sex=1, age=56}, User{name='孙尚香', sex=2, age=22}], 法师=[User{name='诸葛亮', sex=1, age=48}, User{name='貂蝉', sex=2, age=37}]}
Map<String, List<User>> groupingBy = list.stream().collect(Collectors.groupingBy(user -> user.role));//按user.role分组
//{辅助={1=[User{name='刘禅', sex=1, age=18}]}, 打野={1=[User{name='韩信', sex=1, age=27}]}, 射手={1=[User{name='鲁班', sex=1, age=56}], 2=[User{name='孙尚香', sex=2, age=22}]}, 法师={1=[User{name='诸葛亮', sex=1, age=48}], 2=[User{name='貂蝉', sex=2, age=37}]}}
Map<String, Map<Integer, List<User>>> collect = list.stream().collect(Collectors.groupingBy(
user -> user.role,//按user.role分组
Collectors.groupingBy(user -> user.sex)//分组中再按 user.sex分组
));
HashMap<String, Map<Integer, List<User>>> collect1 = list.stream().collect(Collectors.groupingBy(
user -> user.role,//按user.role分组
HashMap::new,//返回指定map,不指定则是返回Map对象
Collectors.groupingBy(user -> user.sex)//分组中再按 user.sex分组
));
//{false=[User{name='刘禅', sex=1, age=18}, User{name='孙尚香', sex=2, age=22}], true=[User{name='诸葛亮', sex=1, age=48}, User{name='貂蝉', sex=2, age=37}, User{name='鲁班', sex=1, age=56}, User{name='韩信', sex=1, age=27}]}
Map<Boolean, List<User>> partitioningBy = list.stream().collect(Collectors.partitioningBy(user -> user.age > 25));
}
4.4、接合(joining)
- joining() :字符串直接拼接
- joining(CharSequence delimiter) :中间加上分隔符
- joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix) :加上前缀和后缀
//由于joining接收的是CharSequence类型,所以需要映射一下
list.stream().map(user -> user.name).collect(Collectors.joining());
list.stream().map(user -> user.name).collect(Collectors.joining("-"));
list.stream().map(user -> user.name).collect(Collectors.joining("-", "前缀", "后缀"));
4.5、规约(reducing)
规约和stream的规约是一样的,这里不做笔记了
4.6、映射(mapping)
//等效于 list.stream().map(user -> user.name).collect(Collectors.toList());
list.stream().collect(Collectors.mapping(user -> user.name, Collectors.toList()));
4.7、收集后再处理(collectingAndThen)
String collect = list.stream().collect(
Collectors.collectingAndThen(
Collectors.mapping(user -> user.name, Collectors.joining("-")),
s -> "apply " + s
));
System.out.println(collect);// apply 诸葛亮-貂蝉-鲁班-刘禅-韩信-孙尚香
网友评论