双括号初始化的替代方法

4
我有一个以以下形式的嵌套集合:
HashMap<String, HashMap<String, List<String>>> errorList;

现在我使用双大括号内联初始化它,像这样:
errorList.put(tempName, new HashMap<String, List<String>>() {{
    put("upl", new ArrayList<String>() {{ add("Y"); add("Upload Success"); }});
}});

这是一个 foreach 循环,其中 tempName 的值在每次迭代中都会更改。 我这样做是因为我不能使用 List<String>HashMap<String,List<String>> 的实例,因为每次我更改该实例中的值时都会反映在它所嵌套的集合中。因此,我被迫使用双括号初始化创建新的实例。

问题是:我想使用一个列表对象。而不是

new ArrayList<String>() {{ add("Y"); add("Upload Success"); }}

我想使用一个变量。
我该怎么做?

2
如果你想使用一个变量,为什么不直接使用它呢? - M. Prokhorov
很抱歉,我还没有完全理解您的问题。请问您能否提供一个“最小化、完整化和可验证”的示例(MCVE)吗?谢谢! - Ole V.V.
这段代码至少看起来很恐怖,你应该使用对象而不是那么多集合。这根本无法维护。 - Marc
我只是在Spring控制器中使用它,以便我可以传递一个错误列表来填充视图(jsp)中的错误表。范围仅限于该控制器方法和视图。我认为这个数据对象将为我在视图方面提供很大的灵活性。 - kaattaalan
可能是Java“双括号初始化”的效率问题的重复。 - kaattaalan
1个回答

6

改为:

new ArrayList<String>() {{ add("Y"); add("Upload Success"); }}

您可以使用以下内容:

Arrays.asList("Y", "Upload Success")

这会给你一个固定大小的列表。如果你希望稍后能够添加或删除元素,请将其转换为 ArrayList

new ArrayList<>(Arrays.asList("Y", "Upload Success"))

当然,在将此列表放入映射结构之前,您可以将其放入自己的变量中。

如果您想要放置[Y,上传成功][N,上传失败]并确保列表不在映射条目之间共享,则有一个建议:首先,在循环外部:

final List<String> successList = Arrays.asList("Y", "Upload Success");
final List<String> failureList = Arrays.asList("N", "Upload Failed");

然后在你的循环中:

if (wasSuccessful) {
    errorList.put(tempName,
                  Collections.singletonMap("upl", new ArrayList<>(successList)));
} else {
    errorList.put(tempName,
                  Collections.singletonMap("upl", new ArrayList<>(failureList)));
}

你可以进一步发挥这个想法并在循环外部构建地图。如果你想要内部地图成为HashMap,只需要转换为new HashMap<>(Collections.singletonMap("upl", new ArrayList<>(successList)))
你可能已经注意到我完全避免了双括号初始化。虽然它很简短,但从概念和性能上来说都具有开销。每次创建一个新的匿名子类,我认为这是不必要的。

你能告诉我这段代码中singletonMap的作用吗?内部哈希映射表还有其他键(共4个)。它们代表了上传数据中存在的不同错误类型。 - kaattaalan
这样的问题最容易通过查阅Collections文档来回答(http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#singletonMap-K-V-)。是的,既然您想要在其中放置更多元素,按照我所描述的转换为`HashMap`即可。 - Ole V.V.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接