美文网首页
一些常用的Stream流和Lambda表达式的结合

一些常用的Stream流和Lambda表达式的结合

作者: SILENCE_SPEAKS | 来源:发表于2020-08-10 18:47 被阅读0次

    一.将一个对象集合中的某个属性转换为一个集合

    List<T> propertyList = DOList.stream().map(DO::getProperty).collect(Collectors.toList());
    

    1.如果获取的属性需要进行类型转换

    例:List<Integer> propertyList = DOList.stream( ).map(v -> Integer.valueOf(v.getProperty())).collect(Collectors.toList());
    

    2.如果在进行类型转换时有空值则会报错(需排除空值)
    (以String类型转换为Integer为例,map和 filter可以视情况交换使用顺序)

    例:List<Integer> propertyList= DOList.stream()
                    .filter(v -> v.getProperty() != null && !"".equals(v.getProperty ()))
                    .map(v -> Integer.valueOf(v.getProperty()))
                    .collect(Collectors.toList());
    

    3.转换集合时只保留另外一个集合(list)中存在的值

    例:List<Integer> propertyList = DOList.stream()
                    .filter(v -> list.contains(v.getProperty()))
                    .map(v -> Integer.valueOf(v.getProperty()))
                    .collect(Collectors.toList());
    

    4.将一个集合转换成字符串用","隔开

    例:String string = list.stream().collect(Collectors.joining(","));
    (如果是转换对象集合中的一个属性,则可以使用map映射到这个属性再collect)
    

    二.将一个对象集合的属性和对象自身转换为一个Map集合

    注:(Function.identity() 可替换为 x -> x)

    例:Map<T, DO> DOMap = DOList.stream().collect(Collectors.toMap(DO::getProperty, Function.identity()));
    

    1.当集合(DOList)中存在重复值,转换为Map时会因为key重复而报错:Duplicate key(解决方法:合并key)

    1.用后面的 value 覆盖前面的 value
    例:Map<T,DO> DOMap = DOList.stream().collect(Collectors.toMap(DO::getProperty, Function.identity(), (k1,k2) -> k2));
    
    2.将前面的 value 和后面的value拼接起来
    例:Map<T,T> propertyMap = DOList.stream().collect(Collectors.toMap(DO::getProperty1, DO::getProperty2, (k1,k2) -> k1+","+k2));
    
    3.合并 list 集合为一个集合
    例:Map<T,List<T>> listMap = DOList.stream().collect(Collectors.toMap(DO::getProperty, DO::getList, (List<T> list1,List<T> list2) -> {list1.addAll(list2);return list1;}));
    
    4.合并 指定属性值 为一个集合
    Map<T,List<T>> listMap = 
    DOList.stream().collect(Collectors.groupingBy(DO::getProperty1, Collectors.mapping(DO::getProperty2, Collectors.toList())));
    

    2.当需要根据集合(DOList)中某个属性进行分组时,可以使用 Collectors.groupingBy()

    1.Collectors.groupingBy() 可以嵌套使用
    例:Map<T, Map<T, List<DO>>> DOMap = DOList.stream()
                        .collect(Collectors.groupingBy(DO::getProperty1,
                                Collectors.groupingBy(DO::getProperty2)));
    
    2.Collectors.groupingBy() 可以和 Collectors.toMap() 结合使用
    例:Map<T, Map<T, T>> DOMap = DOList.stream()
                        .collect(Collectors.groupingBy(DO::getProperty1,
                                Collectors.toMap(DO::getProperty2, DO::getProperty3,
                                        (k1, k2) -> new BigDecimal(k1).add(new BigDecimal(k2)).toString())));
    <!-- 注:这里以 DO 中 property3 属性为数值字符串时,进行对数值字符串类型的聚合 -->
    
    3.对象集合根据某个属性分组的map根据键值进行排序
    List<Map.Entry<T, List<DO>>> sectionDOList = DOMap.entrySet().stream().sorted(Map.Entry.comparingByKey()).collect(Collectors.toList());
    

    三.对象集合中某一属性相关统计(求和、最大、最小、平均)

    1.求和
    double sum = DOList.stream().mapToDouble(DO::getProperty).sum();
    2.最大值
    double max = DOList.stream().mapToDouble(DO::getProperty).max();
    3.最小值
    double min = DOList.stream().mapToDouble(DO::getProperty).min();
    4.平均值
    double ave = DOList.stream().mapToDouble(DO::getProperty).average();
    
    #注:除了 mapToDouble(),还有 mapToInt ()、mapToLong();
    

    1.遇到统计 BigDecimal 类型的数据

    1.求和
    BigDecimal sum = DOList.stream().map(DO::getProperty).reduce(BigDecimal.ZERO, BigDecimal::add);
    2.最大值
    BigDecimal max = DOList.stream().map(DO::getProperty).max(BigDecimal::compareTo).get();
    3.求最小值
    BigDecimal min = DOList.stream().map(DO::getProperty).min(BigDecimal::compareTo).get();
    4.求平均值
    BigDecimal ave = DOList.stream().map(User::getProperty).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(DOList.size()), 2, BigDecimal.ROUND_HALF_UP);
    

    四.Stream流使用

    1.筛选

    • filter(boolean):过滤(boolean为true时往后执行);
    • distinct():去重;
    • limit(n):截短流(只获取符合条件的 n 条数据);
    • skip(n):跳过元素(跳过满足条件的前 n 条数据);

    2.映射

    • map:将一个类型元素转为另一个类型的元素;
    • flatMap:把一种流转成另一种流,并将转换后的流合并成一个流;

    3.查找和匹配

    • allMatch(boolean):是否匹配所有元素;
    • anyMatch(boolean):是否匹配至少一个元素;
    • noneMatch(boolean):是否没有任何元素匹配;
    • findFirst():返回流中的第一个元素;
    • findAny():返回流中的任意一个元素;
    • reduce(a, b):a(是总变量的初始值),b(函数式接口的实现类,一般使用Lambda表达式);

    4.改变内部元素

    • peek():可用于修改集合中的属性,可用于输出信息

    五. 根据对象集合中的某个属性对这个集合进行"排序/去重"

    1. 排序
    sorted():它使用自然顺序对流的元素进行排序。元素类必须实现Comparable接口

    集合排序
    1_1 集合升序排序
    list.stream().sorted().collect(Collectors.toList());
    1_2 集合降序排序,自然序降序使用Comparator提供reverseOrder()方法
    list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
    
    对象集合排序
    2_1 对象集合按某一属性升序排序
    DOList.stream().sorted(Comparator.comparing(DO::getProperty)).collect(Collectors.toList());
    2_2 对象集合按某一属性降序排序,使用Comparator提供reversed()方法
    DOList.stream().sorted(Comparator.comparing(DO::getProperty).reversed()).collect(Collectors.toList());
    
    附加:
    对象集合根据某个属性排序(属性为字符串类型数值)
    3_1 正序
    DOList.sort((o1, o2) -> Integer.compare(Integer.valueOf(o1.getProperty()), Integer.valueOf(o2.getProperty())));
    3_2 倒叙
    DOList.sort((o1, o2) -> -1 * Integer.compare(Integer.valueOf(o1.getProperty()), Integer.valueOf(o2.getProperty())));
    

    2. 去重
    使用Comparator.comparing获取到指定去重属性,TreeSet实现去重
    注:Comparator还有"comparingInt()"、"comparingLong()"、"comparingDouble()"

    ArrayList::new用来转换结果为List集合
    List<DO> DODistinctList = DOList.stream()
            .collect(Collectors.collectingAndThen(Collectors.toCollection(
                    () -> new TreeSet<>(Comparator.comparing(DO::getProperty))), ArrayList::new));
    
    也可以直接去重之后转化为Set
    Set<DO> DOSet = DOList.stream().collect(Collectors.toCollection(
            () -> new TreeSet<>(Comparator.comparing(DO::getProperty))));
    

    相关文章

      网友评论

          本文标题:一些常用的Stream流和Lambda表达式的结合

          本文链接:https://www.haomeiwen.com/subject/hwljdktx.html