Java HashMap是否要求值是不可变的?

cru*_*fux 2 java hashmap

我正在学习Java HashMapClass(Key,Value),并发现为什么Key需要将Immutable它添加到hash之后稍后更改它可能在错误的桶中.

但那怎么样Value?它需要Immutable也是吗?

这来找我,因为我最近遇到一个问题,我有怪异的行为(即没有在地图上的键返回真containsKey()当我使用),AtomicIntegeraddAndGet()方法更改值.

然后,new Integer()每当我需要更改与键对应的值并解决问题时,我就切换到put .

编辑

那么这只是要求Immutable,但这里是代码:

`

HashMap<Long , PreparedStatement> hash_map= new HashMap<Long, PreparedStatement>(); 
HashMap<Long , Integer> hash_map_count = new HashMap<Long , Integer>();

//some code here , lets say phone value comes to a function and function contains this code

 if(hash_map.containsKey( phone)) // present
        {
            ps_insert = (PreparedStatement)hash_map.get( phone);
            count_temp = hash_map_count.get( phone);

            if(count_temp == null)
            {
                System.out.println("************"+ phone);

            }

            count_temp.addAndGet(1); //no need to re-insert into map as value changed by +1 here.
        System.out.println("count : "+count_temp.get()); // 

    }
    else
    {
        ps_temp = conn.prepareStatement("INSERT into T_"+ phone+" VALUES (?,?,?,?,?,?,?)");
        hash_map.put( phone,ps_temp);
        count_temp = new AtomicInteger(1);
        hash_map_count.put( phone, count_temp);
        ps_insert = ps_temp;
        System.out.println("new phone :"+ phone+" count :"+count_temp.get());
    }
Run Code Online (Sandbox Code Playgroud)

问题是******在count_temp中打印了手机(即我得到了null).当我插入AtomicInteger手机时我可以这样做然后我查了一下,发现手机从未插入哈希地图并且仍然containsKey()返回这是真的.

现在任何人都可以解释为什么会发生这种情况以及为什么要更改Integer()并插入new Integer(changed value)更正它?

Dav*_*INO 5

可以修改地图的价值.

还可以修改密钥.关键需要遵循的条件equals()hashCode()之前和修改之后将给出(在的情况下,用相同的输入值相同的结果equals()).此外,如果可以修改密钥,通常它们是不可修改的.

为了更好地说明密钥可以修改的原因,我添加了一些关于HashMap如何工作以及如何编码ModifiableKey的解释.

如何使用HashMap:

在内部,HashMap使用Entry数组,其中Entry是一个tern(Key,Value,Entry).

table

0 --> {K, V, E} --> {K, V, null}
1 --> {k, V, null}
2
3
4 --> {K, V, null}
5
Run Code Online (Sandbox Code Playgroud)

这是get()的代码

 public V get(Object key) {
     if (key == null)
        return getForNullKey();
     int hash = hash(key.hashCode());
     for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {
         Object k;
         if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
             return e.value;
     }
     return null;
 }
Run Code Online (Sandbox Code Playgroud)

如您所见,首先计算hashCode出密钥.然后使用hashCode在表中查找索引.如果地图中存在a Key,则可以通过该位置的Entry元素的链接列表来循环.要检查该键是否存在,使用equals()方法(在for循环内).

如何构建可在地图中使用的可修改密钥

因此,假设您要使用以下类作为键.

public class ModifiableKey {
    private String unmodifiablePart;
    private String modifiablePart;


    public ModifiableKey(String unmodifiablePart) {
        this.unmodifiablePart = unmodifiablePart;
    }

    public String getUnmodifiablePart() {
        return unmodifiablePart;
    }

    public boolean equals(Object obj) {
        ModifiableKey mk = (ModifiableKey) obj;
        return unmodifiablePart.equals(mk.getUnmodifiablePart());
    }

    public int hashCode() {
        return unmodifiablePart.hashCode();
    }

    public void setModifiablePart(String modifiablePart) {
        this.modifiablePart = modifiablePart;
    }

    public String getModifiablePart() {
        return modifiablePart;
    }
}
Run Code Online (Sandbox Code Playgroud)

这个类是可以修改的.您可以根据需要更改属性的值modifiablePart.但它可以用作地图的关键因素,equals并且hashCode当modifiablePart改变值时不会改变它们的行为.