Java - 更新 HashMap 值的最佳方式 - 传递值/引用相关

Posted

技术标签:

【中文标题】Java - 更新 HashMap 值的最佳方式 - 传递值/引用相关【英文标题】:Java - Best way to update HashMap value - Pass by value/reference related 【发布时间】:2014-10-14 00:17:00 【问题描述】:

我有一个带有一些数据的 HashMap。看下面的代码...

HashMap<String, Double[]> map; //Already populated with data

Double[] results = map.get(key);
updateArray(results); //This function makes changes to the results array.
map.put(key, results);

...我的问题是 map.put(key, results) 是否必要?

我仍然对 Java 的值传递和引用传递性质有些困惑。需要明确的是,在第一行代码中,我们得到了对 Double 数组的引用,对吗?因此,第二行的函数应该正确地更新 HashMap 中的 Double 数组……这似乎会使第三行的 map.put() 变得多余。

看别人的HashMap相关代码,好像一直在用put()方法。我只是想确保在没有 put() 方法的情况下这样做不会产生任何不可预见的后果。

感谢您的任何意见!

【问题讨论】:

集合和数组混用通常不是一个好主意。 当你写了一个小测试程序来找出答案时发生了什么?至于您对 pass-by-value 与 pass-by-reference(Java 甚至不支持)的混淆,我强烈建议您阅读 this 然后 this。 @BackSlash Map 是一种集合,HashMap 是它的一种实现。 您观察到的使用“put”的示例可能是存储不可变值。他们正在替换它们,而不是修改它们,这需要再次调用“put” @Fitzy123 我的意思是解决您对其他人使用 HashMap 的观察。您说“他们似乎总是使用 put() 方法。”这很可能是因为存储在其 HashMap 中的值是不可变的,这意味着它们无法更改。对象可以从它们派生出来,但内存中的实际对象不能更改。例如,如果我们想“修改”存储在 HashMap 中的 String,我们可以从中派生另一个 String,但最终我们必须调用“put”来替换原始 String。 【参考方案1】:

考虑以下示例。

Map<String, List<Double>> map = new HashMap<>();

List<Double> list1 = new ArrayList<>(); 
list1.add(1.0); 
list1.add(2.0);

map.put("1", list1);

现在,如果您执行以下操作,地图将自动更新。这是因为 map 持有对实际列表对象的引用。当我们更新相关列表时,map 会在没有任何更新的情况下看到该更改。

List<Double> list2 = map.get("1");
list2.add(10.0);
System.out.println(map);

上面的打印语句将给出以下输出,这将回答问题。

1=[1.0, 2.0, 10.0]

【讨论】:

【参考方案2】:
HashMap<String,String> map = new HashMap<>();
map.put("key", "value");

RestAssured.baseURI = BASE_URL;
RequestSpecification request = RestAssured.given();
request.auth().preemptive().basic("Username", "Password").body(map).put("url");
System.out.println("The value of the field after change is: "  + map.get("key"));

【讨论】:

您好,如果您能解释一下您的回答,说明您的回答如何/为什么这是给定问题的理想解决方案,并且只发布一些源代码,那就太好了。【参考方案3】:
updateArray(results);

这将更新结果对象(其中包含不可变对象的集合,即字符串对象),这意味着当您更新(结果/字符串)对象的值时,它将在结果对象引用下创建另一个字符串。所以如果你想在 map 下看到变化,你必须把它放在 map 中。

my question is whether or not the map.put(key, results) is even necessary? 

map.put(key,results); // will only reflect the changes in map

【讨论】:

【参考方案4】:

在显示的代码中,完全没有必要。来自map.get(key) 的返回值存储在变量results 中,而results之后永远不会分配给。因此,传递给map.put()results 的值保证与从map.get(key) 得到的值相同。无论类型如何,都是如此。

在这种情况下调用map.put(key, results) 和不调用它略有不同——如果resultsmap.get(key) 的结果)是nullmap.put(key, results) 将在其中添加一个null 值以前不在那里。 (HashMap 允许 null 值。)

【讨论】:

【参考方案5】:

如果您正在修改您从HashMap 检索到的引用值所引用的对象,那么在同一个HashMap 中替换它的条目是没有意义的。

如果您要修改引用,则确实需要替换它。

【讨论】:

【参考方案6】:

map.put(key, results) 仅在 map.get(key) 返回 null 时才是必需的,因为在这种情况下,您应该创建一个新数组并将其放入映射中。

如果map.get(key) 返回一个非空数组,updateArray(results) 将更新该数组,无需再次将相同的数组放入Map

所以,总而言之,这段代码涵盖了所有情况:

HashMap<String, Double[]> map; //Already populated with data
...
Double[] results = map.get(key);
if (results == null) 
    results = new Double[someLength];
    map.put(key, results);

updateArray(results);

现在,如果您的 Map 的值是不可变的类,例如 String 或 Integer,您必须在 Map 中放置一个新实例才能替换它,因为您无法更改现有值.

【讨论】:

【参考方案7】:

Map.get(Object) 只是返回对所述数组的引用,它将数组的内容复制到新数组。因此,您对Map.get(Object) 返回的数组所做的任何更改都将反映在存储在Map 中的数组中,因为它们是相同的数组。因此,在这种情况下调用 Map.put(Object,Object) 是完全多余的。

【讨论】:

以上是关于Java - 更新 HashMap 值的最佳方式 - 传递值/引用相关的主要内容,如果未能解决你的问题,请参考以下文章

遍历 HashMap 的 5 种最佳方式,我不信你全知道!

遍历 HashMap 的 5 种最佳方式,我不信你全知道!

遍历 HashMap 的 5 种最佳方式

具有软引用值的HashMap实现

Java常见小知识点(持续更新...)

HashMap集合类 5种最佳遍历方式