JDK1.8特性: Stream 流对象常用方法,groupingBy,forEach,distinct

一:Stream流介绍

  1. “流”是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
  2. “集合讲的是数据,流讲的是计算”
  3. Stream操作可以是中间操作,也可以是完结操作。 
    1. 完结操作:返回某种类型的值   
    2. 中间操作:返回流对象本身
  4. 可以通过多次调用同一个流操作方法来将操作结果串起来。
  5. Steam自己不会存储元素,且不会改变源对象。
  6. Stream会返回一个持有结果的新Stream。

二:Stream操作的3大步骤

  1. 创建Stream
  2. 中间操作
  3. 终止操作(终端操作)

三:常用API

  1. filter:过滤;peopleList.stream().filter(e -> e.getAge() > 1)
  2. map:将函数转为其他流或提取信息;如:peopleList.map(People::getAge)
  3. mapToInt:提取值,并转为int类型;如:peopleList.mapToLong(People::getAge).sum();
  4. mapToIntLong:如mapToInt,只是转换类型不一样;
  5. mapToDouble:如mapToInt,只是转换类型不一样;
  6. flatMap:
  7. flatMapToInt
  8. flatMapToDouble
  9. flatMapToLong
  10. distinct:去重复;如:peopleList.stream().map(People::getName).distinct().collect(Collectors.toList());
  11. sorted:排序;如:peopleList.stream().sorted(Comparator.comparing(People::getAge).reversed()).findFirst().orElse(new People());
  12. limit:取前几个;peopleList.stream().limit(1).collect(Collectors.toList());
  13. skip:跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。如:peopleList.stream().skip(1).collect(Collectors.toList());
  14. collect:接口中方法,定义了如果对流结果进行操作:如:.collect(Collectors.toList());count
  15. anyMatch:检查至少一个匹配(返回类型boolean);如:peopleList.stream().anyMatch(e -> e.getAge() > 1);
  16. noneMatch:检查是否没有匹配的元素
  17. findFirst:返回第一个结果(返回类型:Optional);peopleList.stream().findFirst().orElse(new People());
  18. findAny:返回任意个结果:

Optional:容器管理器

四:demo

package test;


import com.google.common.collect.Lists;
import org.junit.Test;

import java.util.List;
import java.util.stream.Collectors;

public class test {

    @Test
    public void streamTest() {

        List<People> peopleList = Lists.newArrayList();
        peopleList.add(new People(1, 1L));
        peopleList.add(new People(2, 1L));
        peopleList.add(new People(1, 3L));
        peopleList.add(new People(4, 4L));

        /**
         * peopleList.stream():得到一个流对象
         * .map: map方法参数为Function函数式接口
         *  map:是一个对于流对象的中间操作,通过给定的方法,它能够把流对象中的每个元素对应到另外一个对象上。
         * 整体解释:得到people的age值,并输出list
         */
        peopleList.stream().map(People::getAge);
        List<Integer> age = peopleList.stream().map(People::getAge).collect(Collectors.toList());


        System.out.println(age);//[1, 2, 1, 4]
        /**
         * 得到去重复distinct的list
         */
        age = peopleList.stream().map(People::getAge).distinct().collect(Collectors.toList());
        System.out.println(age);//[1, 2, 4]

        /**
         * Filter是一个中间操作,因此允许我们在返回的基础之上再进行其他流的操作。
         * Filter接受一个Predicate接口类型的变量,并将所有流对象中的元素进行过滤。
         * forEach:接受一个function接口类型的变量,用来执行对每一个元素的操作。
         * forEach是一个中止操作。它不返回流,所以哦我们不能再调用其他的流操作。
         * 解释:得到peoplea对象age是1的,并在控制台打印出来。
         */
        peopleList.stream().filter((s) -> s.getAge() == 1).forEach(System.out::println ());
    }

    /**
     * Sorted是一个中间操作,能够返回一个排过序的流对象的视图。流对象中的元素会默认按照自然顺序进行排序,
     * 除非你自己指定一个Comparator接口来改变排序规则.
     *
     * <p>
     * 一定要记住,sorted只是创建一个流对象排序的视图,而不会改变原来集合中元素的顺序。原来string集合中的元素顺序是没有改变的
     */
    @Test
    public void useStreamSort() {
        // Stream<T> sorted();返回Stream接口
        // 另外还有一个 Stream<T> sorted(Comparator<? super T>
        // comparator);带Comparator接口的参数
        stringList.stream().sorted().filter((s) -> s.startsWith("a")).forEach(System.out::println);

        // 输出原始集合元素,sorted只是创建排序视图,不影响原来集合顺序
        stringList.stream().forEach(System.out::println);
    }

    /**
     * 使用并行流
     * 流操作可以是顺序的,也可以是并行的。顺序操作通过单线程执行,而并行操作则通过多线程执行. 可使用并行流进行操作来提高运行效率
     */
    @Test
    public void parallelStreams() {
        // 初始化一个字符串集合
        int max = 1000000;
        List<String> values = new ArrayList<>();

        for (int i = 0; i < max; i++) {
            UUID uuid = UUID.randomUUID();
            values.add(uuid.toString());
        }

        // 使用顺序流排序

        long sequenceT0 = System.nanoTime();
        values.stream().sorted();
        long sequenceT1 = System.nanoTime();

        // 输出:sequential sort took: 51921 ms.
        System.out.format("sequential sort took: %d ms.", sequenceT1 - sequenceT0).println();

        // 使用并行流排序
        long parallelT0 = System.nanoTime();
        // default Stream<E> parallelStream() {
        // parallelStream为Collection接口的一个默认方法
        values.parallelStream().sorted();
        long parallelT1 = System.nanoTime();

        // 输出:parallel sort took: 21432 ms.
        System.out.format("parallel sort took: %d ms.", parallelT1 - parallelT0).println();

        // 从输出可以看出:并行排序快了一倍多
    }

    class People {

        private Integer age;

        private Long id;

        public People(Integer age, Long id) {
            this.age = age;
            this.id = id;
        }

        public Integer getAge() {
            return age;
        }

        public void setAge(Integer age) {
            this.age = age;
        }

        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }
    }
}

 二:anyMatch

private boolean is(VoList voList){

//anyMatch表示,判断的条件里,任意一个元素成功,返回true
//allMatch表示,判断条件里的元素,所有的都是,返回true
//noneMatch跟allMatch相反,判断条件里的元素,所有的都不是,返回true

 return voList.stream()
            .anyMatch(list ->
                Objects.equals(list.getIsTrue(), Boolean.TRUE));
}

三:常用方法


private void test(){

//groupingBy 的使用
Map<String, List<PeopleDO>> Map = peopleDOList.stream().collect(
                Collectors.groupingBy(PeopleDO::getId, Collectors.toList()));

//ofNullable 的使用   
Optional.ofNullable(PeopleDOMap.get(id)).orElse(Lists.newArrayList()).size());


//分组count
  Map<String, Long> Map = peopleDOList.stream().collect(
                    Collectors.groupingBy(PeopleDO::getName, Collectors.counting()));

//forEach使用
peopleDOList.stream().forEach(peopleDO -> {
                peopleCodeSet.add(peopleDO.getCode());
                //do something
            });

//toMap    (first, second) -> second)  为了避免id一致导致的问题
  Map<Long, String> Map = peopleDOList.stream().collect(
            Collectors.toMap(PeopleDO::getId, peopleDO::getCode,(first, second) -> second));
}

//根据key分组返回对象
 Map<String, PeopleDO> cityName2WavCountDoMap = peopleDOList
                .stream()
                .collect(
                    Collectors.toMap(PeopleDO::getName, Function.identity(), (a, b) -> a));


//filter 和 统计求合
 Map<Long, BigDecimal> Map = peopleDOList.stream()
                            .filter(e -> null != e.getName())
                            .collect(Collectors.groupingBy(PeopleDO::getName,  CollectorsUtil.summingBigDecimal(PeopleDO::getMoney)));

//summingBigDecimal 的方法实现
public static <T> Collector<T, ?, BigDecimal> summingBigDecimal(ToBigDecimalFunction<? super T> mapper) {
        return new CollectorImpl<>(() -> new BigDecimal[1], (a, t) -> {
            if (a[0] == null) {
                a[0] = BigDecimal.ZERO;
            }
            a[0] = a[0].add(mapper.applyAsBigDecimal(t));
        }, (a, b) -> {
            a[0] = a[0].add(b[0]);
            return a;
        }, a -> a[0], CH_NOID);
    }

//distinct 去重复
       peopleDOList.stream().distinct()


//得到某个字段的值
    List<Long> idS = peopleDOList.stream()
                .map(PeopleDO::getId)
                .distinct()
                .collect(Collectors.toList());

//map分组count和由小到大排序,并赋值到新集合
    反面教材,hashMap是无序的,这个方法没用
     Map<String, Long> map = Maps.newHashMap();
        peopleList.stream().collect(
            Collectors.groupingBy(People::getName, Collectors.counting())).entrySet().stream().sorted(
            Map.Entry.<String, Long>comparingByValue()
                .reversed()).forEach(e -> map.put(e.getKey(), e.getValue()));


//分组,如有有重复的key并把相同的value替换掉
 Map<Long, String> cabinetIdWithCode = peopleList.stream().collect(
            Collectors.toMap(People::getId, People::getCode,(first, second) -> second));

//根据年龄字段排序(小到大)
peopleList.stream().sorted(
            Comparator.comparing(People::getAge).reversed())
            .collect(Collectors.toList());

//根据年龄字段排序(大到小)
peopleList.stream().sorted(
            Comparator.comparing(People::getAge))
            .collect(Collectors.toList());

//将数组转为流
String[] array = {"a", "b", "c", "d", "e"};
Stream<String> stream1 = Arrays.stream(array);
stream1.findFirst().orElse("Z");


//map根据value排序
       Map.Entry<String, Long> maxSource2BatchMap = peopleList.stream()
            .collect(Collectors.groupingBy(People::getName, Collectors.counting()))
            .entrySet().stream()
            .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
            .findFirst()
            .orElse(null);
//sum
Integer todayCompletedOrderNumSum = nationalRangeVOList.stream()
            .filter(e -> null != e.getTodayCompletedOrderNum())
         .collect(Collectors.summingInt(WarehouseWorkCountVO::getTodayCompletedOrderNum));

//sum
      Integer todayCompletedOrderNumSum = nationalRangeVOList.stream()
            .filter(e -> null != e.getTodayCompletedOrderNum())
            .mapToInt(WarehouseWorkCountVO::getTodayCompletedOrderNum).sum();

备注:

// 
BigDecimal sum = list.stream()
    .map(Model::getNumber)
    .reduce(BigDecimal::add)
    .orElse(BigDecimal.ZERO);
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南无南有

为绿色加绿叶

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值