lambda表达式-02 Stream详解

一、什么是Stream?Stream有什么优点呢?   

    Stream是处理数组和集合的API 

二、Sream的生成操作:

 1  String[] arr = new String[]{"2", "3", "4"};
 2         Stream.of(arr).forEach(System.out::println);
 3         //通过集合来生成
 4         List<String> list = Arrays.asList("a", "b", "c");
 5         Stream<String> stream = list.stream();
 6         stream.forEach(System.out::println);
 7 
 8         Stream<Integer> generate11 = Stream.generate(() ->1);
 9        // generate11.forEach(System.out::println);
10         generate11.limit(10).forEach(System.out::println);
11         //使用iterator
12         Stream<Integer> iterate = Stream.iterate(2, (x) -> x + 1);
13         iterate.limit(10).forEach(System.out::println);

三、Stream的中间操作:注意:只要不到最终执行结果,流是不会执行的,这样大大的节省内存空间。 只要中间是取到的Stream,那么他永远不会执行 可以通过filter测试

  


  List<Integer> list = Arrays.asList(1,2, 3, 4, 5, 6);

//中间操作过滤
// list.stream().filter(x->x%2==0).forEach(System.out::println);
//求和
// int sum =list.stream().mapToInt(x -> x + 1).sum();
//取最大值
// Optional<Integer> max = list.stream().max((a, b) -> a - b);
// System.out.println(max.get());
//求集合的最小值
// System.out.println(list.stream().min((a, b) -> a - b).get());
//取任何一个
System.out.println(list.stream().findFirst().get());
}
 

 四:手写stream的操作:

 

   通过一系列流操作返回一个集合和去重操作:

 

 

  SKIP 跳过多少个  mapToInt转换为Int--实现分页查询的功能

 

 五:创建一组自定义对象

 

 六:基于Stream的项目使用:

 List<OmsBannerManager> selectList = omsBannerManagerMapper.selectList(new QueryWrapper<>());
        List<OmsBannerManager> collect = selectList.stream().filter(x -> null != x.getStartTime() && null != x.getEndTime()).filter(x -> {
            Date startTime = x.getStartTime();
            return compareDate(startTime);
        }).filter(x -> x.getSurplusDay() > 0).map(x -> x.setSurplusDay(x.getSurplusDay() - 1)).map(x ->
             x.getSurplusDay() == 0 ? x.setStatus("1") : x
        ).collect(Collectors.toList());
        this.saveOrUpdateBatch(collect);

 七:ListStream基于对象的使用:

public class StreamTest {
 public static void main(String[] args) {
  List<Person> personList = new ArrayList<Person>();
  personList.add(new Person("Tom", 8900, 23, "male", "New York"));
  personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
  personList.add(new Person("Lily", 7800, 21, "female", "Washington"));

  // 求总数
  Long count = personList.stream().collect(Collectors.counting());
  // 求平均工资
  Double average = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
  // 求最高工资
  Optional<Integer> max = personList.stream().map(Person::getSalary).collect(Collectors.maxBy(Integer::compare));
  // 求工资之和
  Integer sum = personList.stream().collect(Collectors.summingInt(Person::getSalary));
  // 一次性统计所有信息
  DoubleSummaryStatistics collect = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary));

  System.out.println("员工总数:" + count);
  System.out.println("员工平均工资:" + average);
  System.out.println("员工工资总和:" + sum);
  System.out.println("员工工资所有统计:" + collect);
 }
}

 判断有没有大于其中某一个的值:

  boolean a = students.steam().anyMatch(item -> item.getAge() > 35)  判断同学集合有没有年龄大于35岁的。

 七:list转换为map。可以根据String,format设置不同的key,也可以设置不同value

Map<String, String> collect = strings.stream().collect(Collectors.toMap(info -> String.format("%s-%s", info, info), info -> info));

 八:jdk8对map的迭代方式

// JDK8的迭代方式
        map.forEach((key, value) -> {
            System.out.println(key + "" + value);
        });
    }

 九:peek的操作:

  peek最主要的日志打印,debug使用。不会改变流中的值,但是如果流中存放的是对象,是会改变对象的属性。https://blog.csdn.net/weixin_42218169/article/details/117357054

10:将list转换为map

 

 11、concat将两个以上的流合并成一个流

12、reduce的使用

 

 

   1.Math.max(a,b) 可以比较大小 Integer.sum()计算两个数的之和。

  // 1.求出所有年龄的总和
Integer sumAge = Stream.of(
new Person("张三", 18)
, new Person("李四", 22)
, new Person("张三", 13)
, new Person("王五", 15)
, new Person("张三", 19)
).map(Person::getAge) // 实现数据类型的转换
.reduce(0, Integer::sum);
System.out.println(sumAge);

// 2.求出所有年龄中的最大值
Integer maxAge = Stream.of(
new Person("张三", 18)
, new Person("李四", 22)
, new Person("张三", 13)
, new Person("王五", 15)
, new Person("张三", 19)
).map(Person::getAge) // 实现数据类型的转换,符合reduce对数据的要求
.reduce(0, Math::max); // reduce实现数据的处理
System.out.println(maxAge);

Person person = Stream.of(
new Person("张三", 18)
, new Person("李四", 22)
, new Person("张三", 13)
, new Person("王五", 15)
, new Person("张三", 19)
).max((a, b) -> a.age - b.age
).get();

System.out.println(person);
// 3.统计 字符 a 出现的次数
Integer count = Stream.of("a", "b", "c", "d", "a", "c", "a")
.map(ch -> "a".equals(ch) ? 1 : 0)
.reduce(0, Integer::sum);
System.out.println(count);

13、对流中的数据进行聚合运算 当我们使用Stream流处理数据后,可以像数据库的聚合函数一样对某个字段进行操作,比如获得最大值,最小值,求和,平均值,统计数量。

  Optional<Person> maxAge = Stream.of(
                new Person("张三", 18)
                , new Person("李四", 22)
                , new Person("张三", 13)
                , new Person("王五", 15)
                , new Person("张三", 19)
        ).collect(Collectors.maxBy((p1, p2) -> p1.getAge() - p2.getAge()));
 当我们使用Stream流处理数据后,可以像数据库的聚合函数一样对某个字段进行操作,比如获得最大值,最小值,求和,平均值,统计数量。
  .collect(Collectors.summingInt(Person::getAge))
ollect(Collectors.averagingInt(Person::getAge));
 .collect(Collectors.counting());

14、 对流中数据做分组操作

 /**
     * 分组计算
     */
    @Test
    public void test04(){
        // 根据账号对数据进行分组
        Map<String, List<Person>> map1 = Stream.of(
                new Person("张三", 18, 175)
                , new Person("李四", 22, 177)
                , new Person("张三", 14, 165)
                , new Person("李四", 15, 166)
                , new Person("张三", 19, 182)
        ).collect(Collectors.groupingBy(Person::getName));
        map1.forEach((k,v)-> System.out.println("k=" + k +"\t"+ "v=" + v));
        System.out.println("-----------");
        // 根据年龄分组 如果大于等于18 成年否则未成年
        Map<String, List<Person>> map2 = Stream.of(
                new Person("张三", 18, 175)
                , new Person("李四", 22, 177)
                , new Person("张三", 14, 165)
                , new Person("李四", 15, 166)
                , new Person("张三", 19, 182)
        ).collect(Collectors.groupingBy(p -> p.getAge() >= 18 ? "成年" : "未成年"));
        map2.forEach((k,v)-> System.out.println("k=" + k +"\t"+ "v=" + v));

    }

输出结果:
k=李四    v=[Person{name='李四', age=22, height=177}, Person{name='李四', age=15, height=166}]
k=张三    v=[Person{name='张三', age=18, height=175}, Person{name='张三', age=14, height=165}, Person{name='张三', age=19, height=182}]
-----------
k=未成年    v=[Person{name='张三', age=14, height=165}, Person{name='李四', age=15, height=166}]
k=成年    v=[Person{name='张三', age=18, height=175}, Person{name='李四', age=22, height=177}, Person{name='张三', age=19, height=182}]

  多级分组操作:

  /**
     * 分组计算--多级分组
     */
    @Test
    public void test05(){
        // 先根据name分组,然后根据age(成年和未成年)分组
        Map<String,Map<Object,List<Person>>> map =  Stream.of(
                new Person("张三", 18, 175)
                , new Person("李四", 22, 177)
                , new Person("张三", 14, 165)
                , new Person("李四", 15, 166)
                , new Person("张三", 19, 182)
        ).collect(Collectors.groupingBy(
                Person::getName
                ,Collectors.groupingBy(p->p.getAge()>=18?"成年":"未成年"
                )
        ));
        map.forEach((k,v)->{
            System.out.println(k);
            v.forEach((k1,v1)->{
                System.out.println("\t"+k1 + "=" + v1);
            });
        });
    }


输出结果:
李四
    未成年=[Person{name='李四', age=15, height=166}]
    成年=[Person{name='李四', age=22, height=177}]
张三
    未成年=[Person{name='张三', age=14, height=165}]
    成年=[Person{name='张三', age=18, height=175}, Person{name='张三', age=19, height=182}]

15、对数据流的分区 操作  流的分区操作  流的分区操作和分组操作基本一致,就是把map的key 改为true和false

 /**
     * 分区操作
     */
    @Test
    public void test06(){
        Map<Boolean, List<Person>> map = Stream.of(
                new Person("张三", 18, 175)
                , new Person("李四", 22, 177)
                , new Person("张三", 14, 165)
                , new Person("李四", 15, 166)
                , new Person("张三", 19, 182)
        ).collect(Collectors.partitioningBy(p -> p.getAge() > 18));
        map.forEach((k,v)-> System.out.println(k+"\t" + v));
    }
输出结果:
false    [Person{name='张三', age=18, height=175}, Person{name='张三', age=14, height=165}, Person{name='李四', age=15, height=166}]
true    [Person{name='李四', age=22, height=177}, Person{name='张三', age=19, height=182}]

16、对流中的数据做拼接操作:Collectors.joining会根据指定的连接符,将所有的元素连接成一个字符串 

/**
     * 对流中的数据做拼接操作
     */
    @Test
    public void test07(){
        String s1 = Stream.of(
                new Person("张三", 18, 175)
                , new Person("李四", 22, 177)
                , new Person("张三", 14, 165)
                , new Person("李四", 15, 166)
                , new Person("张三", 19, 182)
        ).map(Person::getName)
                .collect(Collectors.joining());
        // 张三李四张三李四张三
        System.out.println(s1);
        String s2 = Stream.of(
                new Person("张三", 18, 175)
                , new Person("李四", 22, 177)
                , new Person("张三", 14, 165)
                , new Person("李四", 15, 166)
                , new Person("张三", 19, 182)
        ).map(Person::getName)
                .collect(Collectors.joining("_"));
        // 张三_李四_张三_李四_张三
        System.out.println(s2);

        String s3 = Stream.of(
                new Person("张三", 18, 175)
                , new Person("李四", 22, 177)
                , new Person("张三", 14, 165)
                , new Person("李四", 15, 166)
                , new Person("张三", 19, 182)
        ).map(Person::getName)
                .collect(Collectors.joining("_", "###", "$$$"));
        // ###张三_李四_张三_李四_张三$$$
        System.out.println(s3);
    }

17、并行流

  获取并行流的两种方式:

 public void test02(){
        List<Integer> list = new ArrayList<>();
        // 通过List 接口 直接获取并行流
        Stream<Integer> integerStream = list.parallelStream();
        // 将已有的串行流转换为并行流
        Stream<Integer> parallel = Stream.of(1, 2, 3).parallel();

18、并行流的测试

  

 

posted @ 2022-03-22 10:03  Jerry&Ming  阅读(66)  评论(0)    收藏  举报