就像标题所说的那样。在迭代其键时,我可以更改HashTable中对象的内部结构吗?我知道我不能改变地图本身,或者至少这样做有风险,但是尽管谷歌搜索我还没有找到任何明确或简单的答案,是否可以改变对象本身的属性在hashmap中。我的直觉不是,因为这可能会改变哈希,但是肯定知道肯定会很好。我也有兴趣在迭代它们时替换键的值。这可能吗?
道歉,如果之前已经回答了很多次。
简而言之,这两种方法是否会按预期工作?
public class Manager {
private Hashtable<MyClassA, BufferedImage> ht1;
private Hashtable<MyClassB, JSlider> ht2;
private Image method1() {
for(MyClassB mcb: ht2.keySet()){
mcb.calculateStuff(ht2.get(mcb).getValue());
//CalculateStuff() doesnt change anything, but if it takes long, the JSliders might be
//changed by the user or a timer, resulting in a new hashCode(), and potentially problems.
}
}
private void method2(){
for(MyClassA mca: ht1.keySet()){
mca.changeInnerStructureOfA(); //Changes the fields of the object mca.
ht1.put(mca.calculateNewImage());
}
}
答案 0 :(得分:2)
不允许在任何情况下改变基于散列的容器的键,而不仅仅是在迭代容器时。这样做的原因是,当散列键位于与键的散列值不对应的散列桶中时,任何更改散列函数值的突变都会使容器处于无效状态。
这是强烈建议仅使用不可变类作为基于散列的容器中的键的原因。
我也有兴趣在迭代它们时替换键的值。这可能吗?
不,这是不可能的。要使用其他键替换容器中的键,您需要先删除该项,然后使用新键重新插入。但是,这会触发并发修改异常。
如果您需要替换大量的密钥,最好的方法是创建一个新的哈希容器,并在迭代原始容器时用key-vale对填充它。
如果您只需要替换少量密钥,请创建描述更改的对象列表(旧密钥,新密钥,值),在迭代原始容器时填充列表,然后遍历更改列表对原始容器进行更改。