如何将流映射到不可变java类?

如何将流映射到不可变java类?,java,java-8,java-stream,Java,Java 8,Java Stream,考虑一段代码: imnport reactor.util.context.Context public Context addAll (Context ctx, Map.Entry<String, Object> hashMap) { Context ctxVar = ctx; for (Map.Entry<String, Object> e : hashMap.entrySet()) { if (e.getValue() != null

考虑一段代码:

imnport reactor.util.context.Context

public Context addAll (Context ctx, Map.Entry<String, Object> hashMap) {
    Context ctxVar = ctx;
    for (Map.Entry<String, Object> e : hashMap.entrySet()) {
        if (e.getValue() != null) {
            ctxVar = ctxVar.put(e.getKey(), e.getValue());
        }
    }
    return ctxVar;
}
imnport reactor.util.context.context
公共上下文addAll(上下文ctx,Map.Entry hashMap){
上下文ctxVar=ctx;
对于(Map.Entry e:hashMap.entrySet()){
如果(如getValue()!=null){
ctxVar=ctxVar.put(e.getKey(),e.getValue());
}
}
返回ctxVar;
}
reactor.util.context.context
是不可变的类。因此,
put
将旧上下文与新的附加值合并,并返回new 上下文

问题是-是否有更紧凑的方法使用Java8流将HashMap“组合”到不可变对象中?(不适用于上下文类)

注意:我已经阅读了关于java stream collect的内容,但它似乎不起作用,因为我必须提供初始
上下文


并在映射后合并多个上下文,但为合并操作重新创建整个上下文我认为太多了。

您可以使用
reduce

Context ctxVar = hashMap.entrySet()
                        .stream()
                        .filter(e -> e.getValue() != null)
                        .reduce(ctx,
                                (c, e) -> c.put(e.getKey(), e.getValue()),
                                (c1, c2) -> c1.putAll(c2));
不过,这看起来确实很浪费(与原始循环浪费的方式相同),因为它会在只需要最后一个实例时创建多个
Context
实例


如果您为
上下文
类(或构造函数)编写一个
静态
方法,该方法接受
映射
,并且只为
映射
的条目创建一个
上下文
实例,则更有意义。但是,我现在注意到您没有编写这个
上下文
类,所以您不能更改它。

您的问题使我感兴趣。我研究了这个问题

以下是我的想法:

package reactor.util.context;

import java.util.Map;
import java.util.Map.Entry;
import static java.util.stream.Collectors.toMap;

public class ContextUtils {
    public static Context putAll(Context context, Map map) {
        if (map.isEmpty()) {
            return context;
        } else {
            Map contextMap = context.stream()
                                    .filter(e -> e.getValue() != null)
                                    .collect(toMap(Entry::getKey, Entry::getValue));
            return new ContextN(contextMap, map);
        }
    }
}
此实用程序方法创建一个新的
上下文
,其中包含来自初始上下文和提供的映射的条目

这个解决方案看起来可能仍然不是最优的,因为它创建了一个新的
HashMap
,initiaCapacity=0,loadFactor=0.75f。事实上,这不是问题,因为
ContextN
本身是
HashMap
的一个子类,具有精确的容量和loadFactor=1。中介映射中的数据将被复制到上下文中,然后由GC收集


注意:实用程序类必须位于包
reactor.util.context
ContextN
package private
,因此无法从其他包访问它。

不应该
Map.Entry hashMap
Map hashMap
?你使用这个变量就像它是一个
Map
。。。您可以实现一个可变版本的
Context
,该版本累积(键、值)对,在流式处理映射时构建它,然后使用
Context.addAll(myMutableContext)将其交给提供的上下文
@DavidSoroko您的方法将为作为
上下文参数提供的
上下文(包含以前的条目)中的每个条目迭代创建一个新的
上下文。