【问题标题】:How map stream to immutable java class?如何将流映射到不可变的 java 类?
【发布时间】:2018-11-22 07:27:26
【问题描述】:

考虑一段代码:

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 “组合”成不可变对象? (不适用于 Context 类)

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

【问题讨论】:

  • 不应该Map.Entry&lt;String, Object&gt; hashMapMap&lt;String, Object&gt; hashMap 吗?您使用该变量,就好像它是 Map

标签: java java-8 java-stream


【解决方案1】:

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

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

【讨论】:

  • 这有点啰嗦,但是...你可以实现一个可变版本的Context,它会累积(键、值)对,在流式传输地图时构建它,然后将其交给使用context.addAll( myMutableContext) 提供上下文
  • @DavidSoroko 您的方法将为Context(包含以前的条目)作为Context.putAll 的参数提供的每个条目迭代地创建一个新的Context
【解决方案2】:

你的问题让我很感兴趣。我研究了这个主题。

这是我想出的:

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,其中包含来自初始上下文和提供的映射的条目。

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

注意:实用程序类必须在包reactor.util.context 中。 ContextNpackage-private,因此无法从其他包访问。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-28
    • 2017-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-21
    相关资源
    最近更新 更多