我有一个对象列表。每个对象都有三个字段:id
,secNumber
和type
。 Type
是枚举,可以具有值'new'
或'legacy'
。有时会发生该列表中的某些对象具有相同的secNumber
a但类型不同的情况。
在这种情况下,我需要删除“ legacy”类型的那个。如何使用Java 8流实现?
答案 0 :(得分:3)
将toMap
与以下内容一起使用:
Collection<T> result = list.stream()
.collect(toMap(T::getSecNumber,
Function.identity(),
(l, r) -> l.getType() == Type.LEGACY ? r : l))
.values();
其中T
是包含secNumber
,id
等的类。
keyMapper
(T::getSecNumber
)从每个对象中提取每个secNumber
。valueMapper
(Function.identity()
)提取我们想要的对象作为地图值,即从源中获取的对象。mergeFunction
(l, r) ->
是我们说的“如果两个给定对象具有相同的键,即getSecNumber
,则将其保留为类型为'NEW'的对象,并使用' LEGACY'”,最后我们调用values()
将地图值累积到Collection中。修改:
您可能正在关注@Tomer Aberbach的评论:
List<T> result =
list.stream()
.collect(groupingBy(T::getSecNumber))
.values()
.stream()
.flatMap(l -> l.stream().anyMatch(e -> e.getType() == Type.NEW) ?
l.stream().filter(e -> e.getType() != Type.LEGACY) :
l.stream())
.collect(toList());
第一个使用toMap
的解决方案假定不能有多个对象具有相同的secNumber
和type
。
答案 1 :(得分:3)
假设objects
是已经声明和初始化的List<ClassName>
:
List<ClassName> filteredObjects = objects.stream()
.collect(Collectors.groupingBy(ClassName::getSecNumber))
.values().stream()
.flatMap(os -> os.stream().anyMatch(o -> o.getType() == Type.NEW) ?
os.stream().filter(o -> o.getType() != Type.LEGACY) :
os.stream()
).collect(Collectors.toList());
我假设Type.LEGACY
类型的对象仅应在存在另一个Type.NEW
类型的secNumber
类型对象的情况下才被过滤掉。我还假设您可能具有相同type
和secNumber
的多个对象,并且可能需要保留这些对象。
请注意,collect(Collectors.groupingBy(ClassName::getSecNumber))
返回的映射类型是secNumber
到List<ClassName>
的类型,因此在其上调用values()
会返回Collection<List<ClassName>>
,它表示具有相同secNumber
的对象分组。
flatMap
部分按secNumber
进行每个分组,检查分组中是否至少有一个Type.NEW
对象,如果有,则过滤掉{{1}类型的对象},否则它只会沿着要展平的对象传递到最终的Type.LEGACY
中。这样做的主要目的是,如果一个分组中只有List<ClassName>
类型的对象,那么它们就不会被排除在最终集合之外。