gpt4 book ai didi

java-8 - 是否可以使用 java 8 流在收集阶段过滤/忽略对象?

转载 作者:行者123 更新时间:2023-12-02 04:12:54 25 4
gpt4 key购买 nike

此问题与 another 相关我不久前发过帖子。

我已经找到了一种按照我想要的方式对数据进行分组的方法。但由于我需要对对象进行分组/映射,当我需要应用一些过滤时,我已经在收集期间关闭了流。我有以下代码:

final Map<TeamDetails, List<Player>> teamDetailsPlayerListMap  = 
dbRows.stream().map(row -> mapDbRowToTeamPlayerPair(row))
.collect(Collectors.groupingBy(TeamPlayerPair::getKey,
Collectors.mapping(TeamPlayerPair::getValue, Collectors.toList())));

final List<Team> teams = teamDetailsPlayerListMap.entrySet().stream()
.map(teamPlayerList -> mapTeamPlayerListToTeam(teamPlayerList))
.collect(Collectors.toList());

我遇到的问题是,某些 dbRow 的 playerNameString 为空或 null。我不想在收集之前进行过滤,就好像 Team 没有玩家一样(例如,只有 1 个 db 行,其中空字符串作为玩家名称),我仍然希望将其包含在我的列表中团队在最后。它只会有一个空的玩家列表。

有什么方法可以在收集期间应用过滤器,以便空或空字符串不会添加到列表中???

我已经能够使用自定义收集器来实现它,如下所示,但我只是想知道是否有一种方法可以在没有自定义收集器的情况下实现它???

Function<Player, Boolean> emptyPlayerNameFilter = new Function<Player, Boolean>() {
@Override
public Boolean apply(Player player) {
return player != null && player.getName() != null && !"".equals(player.getName());
}
};

final Map<TeamDetails, List<Player>> teamDetailsPlayerListMap =
dbRows.stream().map(row -> mapDbRowToTeamPlayerPair(row))
.collect(Collectors.groupingBy(TeamPlayerPair::getKey,
Collectors.mapping(TeamPlayerPair::getValue,
MyCollectors.toFilteredLinkedList(emptyPlayerNameFilter))));

final List<Team> finalTeams = teamDetailsPlayerListMap.entrySet().stream()
.map(teamPlayerList -> mapTeamPlayerListToTeam(teamPlayerList))
.collect(Collectors.toList());

其中 MyCollectors.toFilteredLinkedList() 是:

public class MyCollectors {

public static <T, A extends Collection<T>> Collector<T, ?, A> toFilteredCollection(Supplier<A> collectionFactory, Function<T, Boolean> filter) {
return Collector.of(
collectionFactory,
(acc, entry) -> {
if (filter.apply(entry)) {
acc.add(entry);
}
},
(left, right) -> { left.addAll(right); return left; }
);
}

public static <T> Collector<T, ?, List<T>> toFilteredLinkedList(Function<T, Boolean> filter) {
return toFilteredCollection(LinkedList<T>::new, filter);
}
}

最佳答案

似乎您需要一个filtering收集器,它与mapping类似,但执行过滤。已经implemented在 Java-9 中,但在 Java-8 中不存在。您可以将其放入项目中的某个实用程序类中:

public static <T, A, R> Collector<T, A, R> filtering(
Predicate<? super T> filter, Collector<T, A, R> downstream) {
BiConsumer<A, T> accumulator = downstream.accumulator();
Set<Characteristics> characteristics = downstream.characteristics();
return Collector.of(downstream.supplier(), (acc, t) -> {
if(filter.test(t)) accumulator.accept(acc, t);
}, downstream.combiner(), downstream.finisher(),
characteristics.toArray(new Collector.Characteristics[0]));
}

并像这样使用:

final Map<TeamDetails, List<Player>> teamDetailsPlayerListMap  = 
dbRows.stream()
.map(row -> mapDbRowToTeamPlayerPair(row))
.collect(Collectors.groupingBy(TeamPlayerPair::getKey,
Collectors.mapping(TeamPlayerPair::getValue,
filtering(player -> player != null && player.getName() != null
&& !player.getName().isEmpty(), Collectors.toList()))));

如果您不喜欢在项目中手动添加过滤,您可以使用一些提供此类收集器的第三方库,例如MoreCollectors.filtering() ,可以在我的 StreamEx 中找到图书馆。

关于java-8 - 是否可以使用 java 8 流在收集阶段过滤/忽略对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35637418/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com