zoukankan      html  css  js  c++  java
  • Java8 中根据对象属性去重-集合之间转换

      平时工作中,总会遇到一些数据结构的封装调用,例如(1)List 基础数据类型的集合去重;(2)再或者根据对象的某个属性,多个属性去重;(3)List 集合转换为 Map 集合或者 Set集合等等;今天有时间总结一下Java8中常用的集合转换!

    基础数据

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @ToString
    static class Product {
        private Integer num;
        private String productName;
        private BigDecimal price;
        private String description;
    }
    
    private static List<Product> BASE_DATAS = Lists.newArrayList(
                new Product(1, "虾条", new BigDecimal(3.5), "非常好吃"),
                new Product(2, "虾条", new BigDecimal(3.5), "非常好吃"),
                new Product(3, "果冻", new BigDecimal(5.5), "甜甜的"),
                new Product(4, "果冻", new BigDecimal(5.5), "甜甜的1"),
                new Product(5, "果冻", new BigDecimal(6.0), "甜甜的"),
                new Product(6, "瓜子", new BigDecimal(6.0), "脆脆的"),
                new Product(7, "瓜子", new BigDecimal(6.0), "脆脆的")
        );
    基础数据

    一、List 对象集合根据某个属性去重

    /**
     * 根据对象的某个属性去重
     */
    private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }
    
    // 根据 Product 类中的一个属性去重
    List<Product> productNames = BASE_DATAS.stream().filter(distinctByKey(Product::getProductName)).collect(Collectors.toList());
    productNames.forEach(System.out::println);

    结果:

    CollectorsUtil.Product(num=1, productName=虾条, price=3.5, description=非常好吃)
    CollectorsUtil.Product(num=3, productName=果冻, price=5.5, description=甜甜的)
    CollectorsUtil.Product(num=6, productName=瓜子, price=6, description=脆脆的)

    二、List 对象集合根据多个属性去重

    // 根据 Product 中多个属性去重
    List<Product> products = BASE_DATAS.stream()
            .collect(Collectors.collectingAndThen(
                    Collectors.toCollection(
                            () -> new TreeSet<>(Comparator.comparing(
                                    tc -> tc.getProductName() + ";" + tc.getDescription()))), ArrayList::new));    // 需要设置多个去重的字段信息
    products.forEach(System.out::println);

    结果:

    CollectorsUtil.Product(num=3, productName=果冻, price=5.5, description=甜甜的)
    CollectorsUtil.Product(num=4, productName=果冻, price=5.5, description=甜甜的1)
    CollectorsUtil.Product(num=6, productName=瓜子, price=6, description=脆脆的)
    CollectorsUtil.Product(num=1, productName=虾条, price=3.5, description=非常好吃)

    三、List 转换为 Map 集合

    1)List 封装为 Map 集合,key = 某个属性    value = List<对象>

    // 根据 Product 中的 ProductName 封装 Map 集合【key => productName  value => List<Product>】
    Map<String, List<Product>> productNameMap = BASE_DATAS.stream().collect(Collectors.groupingBy(Product::getProductName));
    for (String key : productNameMap.keySet()) {
        System.out.println(key);
        List<Product> products1 = productNameMap.get(key);
        products1.forEach(System.out::println);
    }

    结果:

    果冻
    CollectorsUtil.Product(num=3, productName=果冻, price=5.5, description=甜甜的)
    CollectorsUtil.Product(num=4, productName=果冻, price=5.5, description=甜甜的1)
    CollectorsUtil.Product(num=5, productName=果冻, price=6, description=甜甜的)
    虾条
    CollectorsUtil.Product(num=1, productName=虾条, price=3.5, description=非常好吃)
    CollectorsUtil.Product(num=2, productName=虾条, price=3.5, description=非常好吃)
    瓜子
    CollectorsUtil.Product(num=6, productName=瓜子, price=6, description=脆脆的)
    CollectorsUtil.Product(num=7, productName=瓜子, price=6, description=脆脆的)

    2)List 封装为 Map 集合,key = 某个属性    value = 某个属性【前提条件:key = 某个属性,这个属性的值要唯一,否则会抛异常 java.lang.IllegalStateException: Duplicate key ......】

    // 根据 Product 中的 num 封装 Map 集合【key => num  value => product】
    Map<Integer, Product> productNumMap = BASE_DATAS.stream().collect(Collectors.toMap(Product::getNum, Function.identity()));
    for (Integer key : productNumMap.keySet()) {
        System.out.println("key = " + key + ", value = " + productNumMap.get(key));
    }

    结果:

    key = 1, value = CollectorsUtil.Product(num=1, productName=虾条, price=3.5, description=非常好吃)
    key = 2, value = CollectorsUtil.Product(num=2, productName=虾条, price=3.5, description=非常好吃)
    key = 3, value = CollectorsUtil.Product(num=3, productName=果冻, price=5.5, description=甜甜的)
    key = 4, value = CollectorsUtil.Product(num=4, productName=果冻, price=5.5, description=甜甜的1)
    key = 5, value = CollectorsUtil.Product(num=5, productName=果冻, price=6, description=甜甜的)
    key = 6, value = CollectorsUtil.Product(num=6, productName=瓜子, price=6, description=脆脆的)
    key = 7, value = CollectorsUtil.Product(num=7, productName=瓜子, price=6, description=脆脆的)

    四、List 转换为 Set 集合

    // 根据 Product 中商品名称去重,展示商品名称
    Set<String> productNames = BASE_DATAS.stream().map(Product::getProductName).collect(Collectors.toSet());
    for (String productName : productNames) {
        System.out.println(productName);
    }

    结果:

    虾条
    果冻
    瓜子

    List 中对象某个属性去重后,按照字符 - 拼接

    // 根据 Product 中商品名称,使用 - 连接符连接
    String productName = BASE_DATAS.stream().map(Product::getProductName).distinct().collect(Collectors.joining("-"));
    System.out.println(productName);
    
    结果:虾条-果冻-瓜子

    每天进步一点点。。。。

  • 相关阅读:
    NOIP201208同余方程
    NOIP模拟赛 最佳组合
    NOIP模拟赛 拓展
    CF1253E Antenna Coverage(DP)
    LOJ6033「雅礼集训 2017 Day2」棋盘游戏 (博弈论,二分图,匈牙利算法)
    CF582E Boolean Function(DP,状态压缩,FMT)
    CF750G New Year and Binary Tree Paths(DP)
    Codeforces Round 596 题解
    AGC008E Next or Nextnext(组合计数,神奇思路)
    ARC082E ConvexScore(神奇思路)
  • 原文地址:https://www.cnblogs.com/blogtech/p/14670679.html
Copyright © 2011-2022 走看看