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 core中的依赖注入、Singleton、Scoped、Transient(一)
    ActionDescriptorProviderContext
    IActionDescriptorProvider
    JWT签名算法中HS256和RS256有什么区别 转载
    JWT 使用的另一种声音
    JWT(Json Web Token):一种在Web应用中安全传递信息的规范 转载
    http 的session 工作原理。
    一般安全机制
    android 上传图片 .html 和android 客户端
    interpolator, typeEvaluator 以及属性动画的参数
  • 原文地址:https://www.cnblogs.com/blogtech/p/14670679.html
Copyright © 2011-2022 走看看