09.Stream常用方法-【案例】串行的Stream流
【案例1】
@Test
public void test1(){
String str1[] = {"迪丽热巴","宋远桥","苏运河","老子","庄子","孙子","红旗"};
String str2[] = {"阿里巴巴","张江","张意识","张子","庄子","孙子","张马"};
List<String> list1 = Arrays.asList(str1);
List<String> list2 = Arrays.asList(str2);
Stream<String> stream1 = list1.stream().filter(s-> s.length() == 3).limit(3);
Stream<String> stream2 = list2.stream().filter(s -> s.startsWith("张")).skip(2);
Stream<String> concat = Stream.concat(stream1, stream2);
concat.map(n -> new PersonDO().builder().name(n).build()).forEach(System.out::println);
}
Result:
PersonDO(name=宋远桥, age=null, height=null)
PersonDO(name=苏运河, age=null, height=null)
PersonDO(name=张子, age=null, height=null)
PersonDO(name=张马, age=null, height=null)
Stream 结果收集
1. 结果收集到集合汇总
收集到list集合中
@Test
@DisplayName("将数组收集到List集合中")
public void test2(){
String str[] = {"aa", "bb", "cc", "dd", "ee"};
List<String> collect = Stream.of(str).collect(Collectors.toList());
System.out.println(collect);
}
Result:
[aa, bb, cc, dd, ee]
收集到set集合中
@Test
@DisplayName("将数组收集到Set集合中")
public void test3(){
String str[] = {"aa", "bb", "cc", "dd", "aa"};
Set<String> collect = Stream.of(str).collect(Collectors.toSet());
System.out.println(collect);
}
[aa, bb, cc, dd]
收集到ArrayList
@Test
@DisplayName("将数组收集到ArrayList")
public void test4(){
String str[] = {"aa", "bb", "cc", "dd", "aa"};
ArrayList<String> collect = Stream.of(str).collect(Collectors.toCollection(() -> new ArrayList<>()));
System.out.println(collect);
}
Result:
[aa, bb, cc, dd, aa]
@Test
@DisplayName("将数组收集到ArrayList--方法引用版")
public void test6(){
String str[] = {"aa", "bb", "cc", "dd", "aa"};
ArrayList<String> collect = Stream.of(str).collect(Collectors.toCollection(ArrayList::new));
System.out.println(collect);
}
[aa, bb, cc, dd, aa]
收集到HashSet
@Test
@DisplayName("将数组收集到HashSet--方法引用版")
public void test7(){
String str[] = {"aa", "bb", "cc", "dd", "aa"};
HashSet<String> collect = Stream.of(str).collect(Collectors.toCollection(HashSet::new));
System.out.println(collect);
}
[aa, bb, cc, dd, aa]
2. 结果收集到数组中
Stream中提供了toArray方法来将结果放到一个数组中,返回值类型是Object[],如果我们要指定返回的类型,那么可以使用另一个重载的toArray(InFuction)方法。
@Test
@DisplayName("将数组收集到数组--Object")
public void test8() {
String str[] = {"aa", "bb", "cc", "dd", "aa"};
Object[] objects = Stream.of(str).toArray();
System.out.println(Arrays.toString(objects));
}
[aa, bb, cc, dd, aa]
@Test
@DisplayName("将数组收集到数组--String[]")
public void test11() {
String str[] = {"aa", "bb", "cc", "dd", "aa"};
String[] strings = Stream.of(str).toArray(String[]::new);
System.out.println(strings);
System.out.println(Arrays.toString(strings));
}
[Ljava.lang.String;@548ad73b
[aa, bb, cc, dd, aa]
Stream 聚合计算
对流中的数据做聚合计算
当我们使用Stream流处理数据后,可以像数据库的聚合函数一样对某个字段进行操作
比如:
- 获得最大值
- 最小值
- 求和
- 平均值
- 统计数量
最大值
@Test
@DisplayName("【案例】:Stream流中数据的聚合计算---获取年龄的最大值")
public void test12() {
Optional<PersonDO> maxAge = Stream.of(
new PersonDO("张三", 18, 1),
new PersonDO("张1", 15, 1),
new PersonDO("张2", 19, 1),
new PersonDO("张3", 12, 1)
).collect(Collectors.maxBy((p1, p2) -> p1.getAge() - p2.getAge()));
System.out.println(maxAge);
System.out.println(maxAge.get());
}
Optional[PersonDO(name=张2, age=19, height=1)]
PersonDO(name=张2, age=19, height=1)
最小值
@Test
@DisplayName("【案例】:Stream流中数据的聚合计算---获取年龄的最小值")
public void test13() {
Optional<PersonDO> maxAge = Stream.of(
new PersonDO("张三", 18, 1),
new PersonDO("张1", 15, 1),
new PersonDO("张2", 19, 1),
new PersonDO("张3", 12, 1)
).collect(Collectors.minBy((p1, p2) -> p1.getAge() - p2.getAge()));
System.out.println(maxAge);
System.out.println(maxAge.get());
}
Optional[PersonDO(name=张3, age=12, height=1)]
PersonDO(name=张3, age=12, height=1)
求和
@Test
@DisplayName("【案例】:Stream流中数据的聚合计算---求年龄和")
public void test14() {
Integer sumAge = Stream.of(
new PersonDO("张三", 18, 1),
new PersonDO("张1", 15, 1),
new PersonDO("张2", 19, 1),
new PersonDO("张3", 12, 1)
).collect(Collectors.summingInt(s -> s.getAge()));
System.out.println(sumAge);
}
64
@Test
@DisplayName("【案例】:Stream流中数据的聚合计算---求年龄和--方法引用版")
public void test14() {
Integer sumAge = Stream.of(
new PersonDO("张三", 18, 1),
new PersonDO("张1", 15, 1),
new PersonDO("张2", 19, 1),
new PersonDO("张3", 12, 1)
).collect(Collectors.summingInt(PersonDO::getAge));
System.out.println(sumAge);
}
64
平均值
@Test
@DisplayName("【案例】:Stream流中数据的聚合计算---求年龄平均值--方法引用版")
public void test15() {
Double avgAge = Stream.of(
new PersonDO("张三", 18, 1),
new PersonDO("张1", 15, 1),
new PersonDO("张2", 19, 1),
new PersonDO("张3", 12, 1)
).collect(Collectors.averagingInt(PersonDO::getAge));
System.out.println(avgAge);
}
16.0
统计数量
@Test
@DisplayName("【案例】:Stream流中数据的聚合计算---求一共多少人--方法引用版")
public void test16() {
Long rows = Stream.of(
new PersonDO("张三", 18, 1),
new PersonDO("张1", 15, 1),
new PersonDO("张2", 19, 1),
new PersonDO("张3", 12, 1)
).collect(Collectors.counting());
System.out.println(rows);
}
4
分组计算
【案例】:分组计算--根据账号对数据进行分组
@Test
@DisplayName("【案例】:分组计算--根据账号对数据进行分组")
public void test17() {
Map<String, List<PersonDO>> map = Stream.of(
new PersonDO("张3", 18, 111),
new PersonDO("张1", 15, 122),
new PersonDO("张2", 19, 103),
new PersonDO("张2", 11, 193),
new PersonDO("张2", 16, 133),
new PersonDO("张3", 12, 144)
).collect(Collectors.groupingBy(PersonDO::getName));
System.out.println(map);
System.out.println("--------------------------------");
map.forEach((k,v)-> System.out.println("k=" + k + ",v=" + v));
}
{张3=[PersonDO(name=张3, age=18, height=111), PersonDO(name=张3, age=12, height=144)], 张2=[PersonDO(name=张2, age=19, height=103), PersonDO(name=张2, age=11, height=193), PersonDO(name=张2, age=16, height=133)], 张1=[PersonDO(name=张1, age=15, height=122)]}
--------------------------------
k=张3,v=[PersonDO(name=张3, age=18, height=111), PersonDO(name=张3, age=12, height=144)]
k=张2,v=[PersonDO(name=张2, age=19, height=103), PersonDO(name=张2, age=11, height=193), PersonDO(name=张2, age=16, height=133)]
k=张1,v=[PersonDO(name=张1, age=15, height=122)]
【案例】:分组计算--根据年龄对数据进行分组
@Test
@DisplayName("【案例】:分组计算--根据年龄对数据进行分组")
public void test18() {
Map<String, List<PersonDO>> collect = Stream.of(
new PersonDO("张3", 18, 111),
new PersonDO("张1", 15, 122),
new PersonDO("张2", 19, 103),
new PersonDO("张2", 11, 193),
new PersonDO("张2", 16, 133),
new PersonDO("张3", 12, 144)
).collect(Collectors.groupingBy(s -> {
return s.getAge() >= 18 ? "成年" : "未成年";
}));
collect.forEach((k, v) -> System.out.println("k =" + k + "; v =" + v));
}
k =未成年; v =[PersonDO(name=张1, age=15, height=122), PersonDO(name=张2, age=11, height=193), PersonDO(name=张2, age=16, height=133), PersonDO(name=张3, age=12, height=144)]
k =成年; v =[PersonDO(name=张3, age=18, height=111), PersonDO(name=张2, age=19, height=103)]
多级分组
【案例】:分组计算--先根据用户名进行分株,再根据成年/未成年进行分组
@Test
@DisplayName("【案例】:分组计算--先根据用户名进行分株,再根据成年/未成年进行分组")
public void test19() {
Map<String, Map<String, List<PersonDO>>> collect = Stream.of(
new PersonDO("张3", 18, 111),
new PersonDO("张1", 15, 122),
new PersonDO("张2", 19, 103),
new PersonDO("张2", 11, 193),
new PersonDO("张2", 16, 133),
new PersonDO("张3", 12, 144)
).collect(Collectors.groupingBy(PersonDO::getName, Collectors.groupingBy(s -> {
return s.getAge() >= 18 ? "成年" : "未成年";
})));
collect.forEach((k, v) -> System.out.println("k =" + k + "; v =" + v));
}
k =张3; v ={未成年=[PersonDO(name=张3, age=12, height=144)], 成年=[PersonDO(name=张3, age=18, height=111)]}
k =张2; v ={未成年=[PersonDO(name=张2, age=11, height=193), PersonDO(name=张2, age=16, height=133)], 成年=[PersonDO(name=张2, age=19, height=103)]}
k =张1; v ={未成年=[PersonDO(name=张1, age=15, height=122)]}
分区操作
对流中的数据做分区操作
Collectors.partitioningBy会根据值是否为true,把集合中的数据分割为两个表,一个true列表,一个false列表。
【案例】:分区操作键为true/false
@Test
@DisplayName("【案例】:分区操作")
public void test20() {
Map<Boolean, List<PersonDO>> collect = Stream.of(
new PersonDO("张3", 18, 111),
new PersonDO("张1", 15, 122),
new PersonDO("张2", 19, 103),
new PersonDO("张2", 11, 193),
new PersonDO("张2", 16, 133),
new PersonDO("张3", 12, 144)
).collect(Collectors.partitioningBy(p -> p.getAge() > 18));
collect.forEach((k, v) -> System.out.println("k =" + k + "; v =" + v));
}
k =false; v =[PersonDO(name=张3, age=18, height=111), PersonDO(name=张1, age=15, height=122), PersonDO(name=张2, age=11, height=193), PersonDO(name=张2, age=16, height=133), PersonDO(name=张3, age=12, height=144)]
k =true; v =[PersonDO(name=张2, age=19, height=103)]
对流中的数据作拼接
Collectors.joining 会根据指定的连接符,将所有的元素连接成一个字符串。
将数据库查询出来的多个数据拼接成一个信息,然后交给前端。
@Test
@DisplayName("【案例】:拼接操作")
public void test21() {
String collect = Stream.of(
new PersonDO("张3", 18, 111),
new PersonDO("张1", 15, 122),
new PersonDO("张2", 19, 103),
new PersonDO("张2", 11, 193),
new PersonDO("张2", 16, 133),
new PersonDO("张3", 12, 144)
).map(PersonDO::getName).collect(Collectors.joining());
System.out.println("collect = " + collect);
}
collect = 张3张1张2张2张2张3
@Test
@DisplayName("【案例】:拼接操作下划线版")
public void test22() {
String collect = Stream.of(
new PersonDO("张3", 18, 111),
new PersonDO("张1", 15, 122),
new PersonDO("张2", 19, 103),
new PersonDO("张2", 11, 193),
new PersonDO("张2", 16, 133),
new PersonDO("张3", 12, 144)
).map(PersonDO::getName).collect(Collectors.joining("_"));
System.out.println("collect = " + collect);
}
collect = 张3_张1_张2_张2_张2_张3
@Test
@DisplayName("【案例】:拼接操作下划线版+前后")
public void test23() {
String collect = Stream.of(
new PersonDO("张3", 18, 111),
new PersonDO("张1", 15, 122),
new PersonDO("张2", 19, 103),
new PersonDO("张2", 11, 193),
new PersonDO("张2", 16, 133),
new PersonDO("张3", 12, 144)
).map(PersonDO::getName).collect(Collectors.joining("_","###","$$$$"));
System.out.println("collect = " + collect);
}
collect = ###张3_张1_张2_张2_张2_张3$$$$
以上都是串行的Stream流。