在hashmap中使用double作为值的问题

时间:2011-11-22 09:04:30

标签: java

我有一个double作为hashmap中的值,键作为String。如果我将作为值添加的变量单独更新到散列映射,而不是在散列映射中更新它,则不会反映更新的值。那是当我使用键获取值时,我得到的值为0.0而不是更新的值。我无法理解为什么会这样。请详细说明一下。此外,是否有其他方法通过更新变量来更新hashmap中的值。我正在谈论的示例代码如下:

import java.util.HashMap;
public class TestDouble{
    public Double d1 = 0.0;
    public Double d2 = 0.0;
    public Double d3 = 0.0;
    private HashMap<String,Double> hm;

    public TestDouble(){
        hm = new HashMap<String,Double>();
        hm.put("D1",d1);
        hm.put("D2",d2);
        hm.put("D3",d3);
    }

    public void updateD1(double d){
        d1 = d;
    }

    public void updateD2(double d){
        d2 = d;
    }

    public void updateD3(double d){
        d3 = d;
    }

   public Double getValue(String key){
        Double val = (Double)hm.get(key);
        return val;
    }

    public static void main(String args[]){
        TestDouble td =new TestDouble();
        td.updateD1(10.10);
        td.updateD2(20.20);
        td.updateD3(30.30);
        System.out.println("Value of D1 from HashMap = "+td.getValue("D1")+" from actual variable = "+td.d1);
        System.out.println("Value of D2 from HashMap = "+td.getValue("D2")+" from actual variable = "+td.d2);
        System.out.println("Value of D3 from HashMap = "+td.getValue("D3")+" from actual variable = "+td.d3);
    }
}

我得到的输出是:

Value of D1 from HashMap = 0.0 from actual variable = 10.1
Value of D2 from HashMap = 0.0 from actual variable = 20.2
Value of D3 from HashMap = 0.0 from actual variable = 30.3

4 个答案:

答案 0 :(得分:8)

Double是不可变的。您无法更新其值。相反,您可以引用Double

的另一个实例

d1引用了0d

Double d1 = 0d;

如果我们进行另一次初始化,它将引用另一个值:

d1 = 1d;

另一方面,HashMap是可变的,即其内部状态可以改变:

Map<String, Double> map = new HashMap<String, Double>();
map.put("first", 0d);
map.put("first", 1d);
System.out.println("first = " + map.get("first"));

输出将是:

first = 1.00

请记住,我们已替换了与密钥first关联的值,但未更新。

答案 1 :(得分:1)

在Java变量中包含对象的引用。最初d1和D1的HashMap条目指向同一个对象(因此它们各自包含相同的引用)。

当您修改变量d1以指向新对象时,变量的值将更改为对此新对象的引用。此更改仅针对d1,D1的HashMap条目仍将原始引用作为其值,因此仍然指向Double 0.00。

答案 2 :(得分:1)

Java使用值传递引用,这意味着您的d1是对值为0.0的Double实例的引用。当你将它放在地图中时,不要将d1放在地图中,而是将d1引用的副本(也指向值为0.0的Double实例)。所以你没有两个引用你的Double,一个来自d1,一个来自地图。当您更改d1时,您不会更改Double的值,而是更改引用d1以指向另一个Double,这不会更改存储在地图中的引用。

要获得所需的效果,您需要存储保留引用的对象并更改对象的值。例如:

import java.util.HashMap;

public class TestDouble {

    private static class Holder {
        Double value = 0.0;
    }

    private HashMap<String,Holder> hm = new HashMap<String,Holder>();;

    private Holder d1 = new Holder();

    public TestDouble(){
        hm = new HashMap<String,Holder>();
        hm.put("D1",d1);
    }

    public void updateD1(double d){
        d1.value = d;
    }

    public Double getValue(String key) {
        return hm.get(key).value;
    }

    public static void main(String args[]){
        TestDouble td =new TestDouble();
        System.out.println("Value of D1 from HashMap = "+td.getValue("D1")+" from actual variable = "+td.d1.value);
        td.updateD1(10.10);
        System.out.println("Value of D1 from HashMap = "+td.getValue("D1")+" from actual variable = "+td.d1.value);
    }
}

答案 3 :(得分:0)

Double是一个不可变的数据类型,就像String一样。因此,当您使用变量来帮助为映射设置值,然后将其设置为其他Double值时,两个Double值是不同的。难怪你为何会得到观察到的行为。