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);

结果:虾条-果冻-瓜子

每天进步一点点。。。。

原文地址:https://www.cnblogs.com/blogtech/p/14670679.html