我有这段代码,可以正常工作,但我觉得它很难看。
@EqualsAndHashCode
public abstract class Actions {
@Getter
private List<ActionsBloc> blocs;
public Actions mergeWith(@NotNull Actions other) {
this.blocs = Stream.of(this.blocs, other.blocs)
.flatMap(Collection::stream)
.collect(groupingBy(ActionsBloc::getClass, reducing(ActionsBloc::mergeWith)))
.values()
.stream()
.filter(Optional::isPresent)
.map(Optional::get)
.collect(toList());
return this;
}
}
ActionsBloc
是一个父类(super class)型,其中包含 Action
列表。
public interface ActionsBloc {
<T extends Action> List<T> actions();
default ActionsBloc mergeWith(ActionsBloc ab) {
this.actions().addAll(ab.actions());
return this;
}
}
我想要做的是根据Class
类型将Actions
的blocs
合并在一起。因此,我按 ActionsBloc::getClass
进行分组,然后通过调用 ActionsBloc::mergeWith
进行合并。
我觉得丑陋的是在collect
上第一个流结束后调用values().stream()
。
有没有一种方法可以只对一个流进行操作并摆脱 values().stream()
,或者我是否必须编写一个自定义 Spliterator?换句话说,我的代码中只有一个 collect
。
最佳答案
您可以使用简化的身份来解决这个问题。一种方法是将 mergeWith
的实现更新为:
default ActionsBloc mergeWith(ActionsBloc ab) {
this.actions().addAll(Optional.ofNullable(ab)
.map(ActionsBloc::actions)
.orElse(Collections.emptyList()));
return this;
}
然后将分组
和缩减
修改为:
this.blocs = new ArrayList<>(Stream.of(this.blocs, other.blocs)
.flatMap(Collection::stream)
.collect(groupingBy(ActionsBloc::getClass, reducing(null, ActionsBloc::mergeWith)))
.values());
编辑:正如 Holger 指出的那样,使用 groupingBy
和 reducing
进一步使用 toMap< 可以更合适地实现
为:
this.blocs = new ArrayList<>(Stream.concat(this.blocs.stream(), other.blocs.stream())
.collect(Collectors.toMap(ActionsBloc::getClass, Function.identity(), ActionsBloc::mergeWith))
.values());
关于java - 我是否需要自定义 Spliterator 来避免额外的 .stream() 调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56684523/