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