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

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

1、使用 toMap 收集器

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

  • 利用了 Collectors.toMap 收集器,将元素映射到它们的 OmsOrderId,然后通过 values() 方法获取去重后的值。
  • 适用于你希望保留重复元素中的第一个元素的情况,它使用了 existing -> existing 的合并函数来解决重复键的问题。
java 复制代码
// 从 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
java 复制代码
// 从 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

java 复制代码
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。

相关推荐
Java致死1 小时前
设计模式Java
java·开发语言·设计模式
源码方舟1 小时前
SpringBoot + Shiro + JWT 实现认证与授权完整方案实现
java·spring boot·后端
2401_cf4 小时前
为什么hadoop不用Java的序列化?
java·hadoop·eclipse
帮帮志4 小时前
idea整合maven环境配置
java·maven·intellij-idea
LuckyTHP5 小时前
java 使用zxing生成条形码(可自定义文字位置、边框样式)
java·开发语言·python
无声旅者7 小时前
深度解析 IDEA 集成 Continue 插件:提升开发效率的全流程指南
java·ide·ai·intellij-idea·ai编程·continue·openapi
Ryan-Joee8 小时前
Spring Boot三层架构设计模式
java·spring boot
Hygge-star8 小时前
【数据结构】二分查找5.12
java·数据结构·程序人生·算法·学习方法
Darkwanderor8 小时前
c++STL-list的模拟实现
c++·list
dkmilk8 小时前
Tomcat发布websocket
java·websocket·tomcat