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);
    
    结果:虾条-果冻-瓜子

    每天进步一点点。。。。

  • 相关阅读:
    [转].net mvc + vuejs 的项目结构
    Outlook IMAP 修改PST文件存储路径
    VS2017 性能优化方法
    查询存储过程所需参数
    如何保障微服务架构下的数据一致性
    sqlserver批量给用户配置存储过程权限
    vue中刷新当前页面或重新加载的两种方法
    vue history模式下的微信支付,及微信支付授权目录的填写,处理URL未注册
    Vue 四行代码实现无感知上拉加载更多
    2019年前端必用正则(js)
  • 原文地址:https://www.cnblogs.com/blogtech/p/14670679.html
Copyright © 2011-2022 走看看