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

时间:2018-11-22 07:27:26

标签: 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) {
            ctxVar = ctxVar.put(e.getKey(), e.getValue());
        }
    }
    return ctxVar;
}

reactor.util.context.Context是不可变的类。因此,put将旧的上下文与新的附加值合并,并返回 new 上下文。

问题是-是否存在使用Java 8流将HashMap组合为不可变对象的更紧凑的方法? (不仅适用于上下文类)

注意:我已经阅读了有关Java流收集的信息,但似乎不起作用,因为我必须提供初始的Context 并在映射后合并多个上下文,但为合并操作重新创建整个上下文,我认为太多了。

2 个答案:

答案 0 :(得分:0)

您可以使用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实例。

如果您编写static类(或构造函数)的Context方法(它接受一个Map并且仅创建一个Context实例,那将更有意义) Map的条目。但是,我现在注意到您没有写这个Context类,所以您不能更改它。

答案 1 :(得分:0)

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

这是我想出的:

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);
        }
    }
}

此实用程序方法创建一个新的Context,其中包含来自初始上下文和提供的映射的条目。

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

注意:实用工具类必须位于软件包reactor.util.context中。 ContextNpackage-private,因此无法从其他软件包中访问。

相关问题