這個問題與another有關,我發佈前不久。是否可以在java 8流的收集階段過濾/忽略對象?
我想出了一種按我想要的方式對數據進行分組的方法。但是由於我需要對集合/映射對象進行分組,所以在我需要應用某些過濾時,我已經在集合期間關閉了流。我有以下代碼:
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());
我的問題是,一些dbRows具有爲playerName
空或空String
。我不想在收集之前過濾,就好像Team
沒有玩家(例如,只有1分貝的空行字符串作爲玩家的名字),我仍然希望在最後的Team
s列表中有。它只會有一個空的球員名單。
有什麼辦法,我可以在收集過程中應用過濾器,以便空或空字符串不會被添加到列表中?
我已經能夠實現它與自定義收集器如下所示,但我只是想知道如果有一種方法,我可以做到這一點沒有自定義收集器?
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);
}
}