09.Stream常用方法-【案例】串行的Stream流

39 阅读7分钟

09.Stream常用方法-【案例】串行的Stream流

【案例1】

image.png

@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列表。

image.png

【案例】:分区操作键为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 = 张312223
@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流。