List根据实体类中某一字段进行去重

本文介绍了在Java中如何使用Collectors.toMap、TreeSet以及StreamUtils.distinctByKey方法对List中的元素进行OmsOrderId字段的去重。方法包括利用toMap的现有值替换策略,TreeSet排序并自动去重,以及自定义的distinctByKey函数辅助流过滤重复元素。
摘要由CSDN通过智能技术生成

List根据实体类中某一字段进行去重


1、使用 toMap 收集器

利用 Collectors.toMap 收集器将流中的元素映射为一个 Map,其中键为 OmsOrderId,值为元素本身。如果存在相同的键(即相同的 OmsOrderId),则使用 (existing, replacement) -> existing 函数来决定保留哪一个元素。最后,通过调用 values() 方法,获取 Map 中的值集合,即去重后的元素集合。

  • 利用了 Collectors.toMap 收集器,将元素映射到它们的 OmsOrderId,然后通过 values() 方法获取去重后的值。
  • 适用于你希望保留重复元素中的第一个元素的情况,它使用了 existing -> existing 的合并函数来解决重复键的问题。
// 从 orderCompanyList 创建一个流,并进行以下操作:
List<StorageDeliveryPrintExcelResp> uniqueOrders = new ArrayList<>(orderCompanyList.stream()
        // 使用 Collectors.toMap 收集器将流中的元素映射为 Map,其中键为 OmsOrderId,值为元素本身。
        .collect(Collectors.toMap(
                StorageDeliveryPrintExcelResp::getOmsOrderId, // 使用 StorageDeliveryPrintExcelResp 对象的 getOmsOrderId 方法作为键
                Function.identity(), // 使用 Function.identity() 作为值,表示保留元素本身
                (existing, replacement) -> existing // 如果存在重复的键,则使用现有的元素替换重复元素,即保留第一个出现的元素
        ))
        // 获取 Map 中的值集合,即去重后的元素集合
        .values());



2、使用 collectingAndThen 收集器和 TreeSet

  • 将流中的元素收集到一个 TreeSet 中,该 TreeSet 按照 OmsOrderId 属性进行比较和排序,同时去除重复元素。
  • 使用 Collectors.collectingAndThen 收集器对 TreeSet 进行后续处理,将其转换为一个新的 ArrayList
// 从 orderCompanyList 创建一个流,并进行以下操作:
List<StorageDeliveryPrintExcelResp> uniqueOrders2 = orderCompanyList.stream().collect(
        // 使用 Collectors.collectingAndThen 收集器,将流中的元素收集为一个列表
        Collectors.collectingAndThen(
                // 使用 Collectors.toCollection 收集器,将元素收集到一个 TreeSet 中
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(StorageDeliveryPrintExcelResp::getOmsOrderId))),
                // 使用 ArrayList::new 将 TreeSet 转换为 ArrayList
                ArrayList::new
        )
);


3、封装StreamUtils

public class StreamUtils {

    public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Set<Object> seen = ConcurrentHashMap.newKeySet();
        return t -> seen.add(keyExtractor.apply(t));
    }

}

List<SalesOrder> collect = orderCompanyList.stream().filter(StreamUtils.distinctByKey(SalesOrder::getOmsOrderId))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
  1. public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {

    这是一个公共静态方法,它是一个泛型方法,参数 T 表示元素的类型。它接受一个 Function 类型的参数 keyExtractor,这个函数用于提取元素的某个属性或标识,以便用于判断元素是否重复。

  2. Set<Object> seen = ConcurrentHashMap.newKeySet();

    这一行创建了一个线程安全的 Set 实例 seen,用于存储已经看到的元素的键(key)。这里使用了 ConcurrentHashMap.newKeySet() 来获取一个基于 ConcurrentHashMap 实现的线程安全的 Set,以确保在多线程环境下的安全性。

  3. return t -> seen.add(keyExtractor.apply(t));

    这一行返回了一个 Predicate<T>,该 Predicate 接受类型为 T 的元素 t,并根据 keyExtractor 提取的键来判断是否将该元素添加到 seen 集合中。如果 seen 集合中不存在该元素的键(即元素是第一次出现),则将该元素的键添加到 seen 集合中,并返回 true;否则返回 false,表示该元素已经存在,不需要再次添加。

总的来说,这段代码的作用是生成一个 Predicate,用于根据指定的键(通过 keyExtractor 函数提取)来判断元素是否重复,如果元素的键是第一次出现,则返回 true,否则返回 false。

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值