Do I need a custom Spliterator to avoid extra .stream() call?(我是否需要自定义 Spliterator 以避免额外的 .stream() 调用?)
问题描述
我有这段代码可以正常工作,但我觉得它很难看.
I have this code which works fine, but I find it ugly.
@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 是一个超类型,其中包含 Action 列表.
ActionsBloc is a super type which contains a list of Action.
public interface ActionsBloc {
    <T extends Action> List<T> actions();
    default ActionsBloc mergeWith(ActionsBloc ab) {
        this.actions().addAll(ab.actions());
        return this;
    }
}
我要做的是根据 Class 类型将 Actions 的 blocks 合并在一起.所以我按 ActionsBloc::getClass 分组,然后通过调用 ActionsBloc::mergeWith 进行合并.
What I want to do is merge blocs of Actions together based on the Class type. So I'm grouping by ActionsBloc::getClass and then merge by calling ActionsBloc::mergeWith.
我觉得丑陋的是在 collect 上结束第一个流之后调用 values().stream().
What I find ugly is calling the values().stream() after the first stream was ended on collect.
有没有办法只对一个流进行操作并摆脱 values().stream(),还是我必须编写一个自定义 Spliterator?换句话说,我的代码中只有一个 collect.
Is there a way to operate only on one stream and get rid of values().stream(), or do I have to write a custom Spliterator? In other words have only one collect in my code.
推荐答案
您可以使用减少标识来解决这个问题.一种方法是将 mergeWith 的实现更新为:
You can work with a reducing identity to sort that out possibly. One way could be to update the implementation of mergeWith as :
default ActionsBloc mergeWith(ActionsBloc ab) {
    this.actions().addAll(Optional.ofNullable(ab)
            .map(ActionsBloc::actions)
            .orElse(Collections.emptyList()));
    return this;
}
然后将grouping和reduction修改为:
this.blocs = new ArrayList<>(Stream.of(this.blocs, other.blocs)
        .flatMap(Collection::stream)
        .collect(groupingBy(ActionsBloc::getClass, reducing(null, ActionsBloc::mergeWith)))
        .values());
Edit:正如 Holger 指出的那样,使用 groupingBy 和 reducing 的用例可以更合适地使用 toMap 为:
Edit: As Holger pointed out such use cases of using groupingBy and reducing further could be more appropriately implemented using toMap as :
this.blocs = new ArrayList<>(Stream.concat(this.blocs.stream(), other.blocs.stream())
        .collect(Collectors.toMap(ActionsBloc::getClass, Function.identity(), ActionsBloc::mergeWith))
        .values());
这篇关于我是否需要自定义 Spliterator 以避免额外的 .stream() 调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:我是否需要自定义 Spliterator 以避免额外的 .stream() 调用?
 
				
         
 
            
        基础教程推荐
- 在 Java 中创建日期的正确方法是什么? 2022-01-01
- 验证是否调用了所有 getter 方法 2022-01-01
- 如何在 JFrame 中覆盖 windowsClosing 事件 2022-01-01
- 大摇大摆的枚举 2022-01-01
- Java 实例变量在两个语句中声明和初始化 2022-01-01
- 不推荐使用 Api 注释的描述 2022-01-01
- 多个组件的复杂布局 2022-01-01
- 如何在 Spring @Value 注解中正确指定默认值? 2022-01-01
- Java Swing计时器未清除 2022-01-01
- 从 python 访问 JVM 2022-01-01
 
    	 
    	 
    	 
    	 
    	 
    	 
    	 
    	 
						 
						 
						 
						 
						 
				 
				 
				 
				