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());
-
public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {这是一个公共静态方法,它是一个泛型方法,参数
T表示元素的类型。它接受一个Function类型的参数keyExtractor,这个函数用于提取元素的某个属性或标识,以便用于判断元素是否重复。 -
Set<Object> seen = ConcurrentHashMap.newKeySet();这一行创建了一个线程安全的
Set实例seen,用于存储已经看到的元素的键(key)。这里使用了ConcurrentHashMap.newKeySet()来获取一个基于ConcurrentHashMap实现的线程安全的Set,以确保在多线程环境下的安全性。 -
return t -> seen.add(keyExtractor.apply(t));这一行返回了一个
Predicate<T>,该Predicate接受类型为T的元素t,并根据keyExtractor提取的键来判断是否将该元素添加到seen集合中。如果seen集合中不存在该元素的键(即元素是第一次出现),则将该元素的键添加到seen集合中,并返回true;否则返回false,表示该元素已经存在,不需要再次添加。
总的来说,这段代码的作用是生成一个 Predicate,用于根据指定的键(通过 keyExtractor 函数提取)来判断元素是否重复,如果元素的键是第一次出现,则返回 true,否则返回 false。