HashMap包含4个元素,但调试

时间:2015-07-21 08:44:54

标签: java hashmap

我使用以下代码定义了HashMap

final Map<OrderItemEntity, OrderItemEntity> savedOrderItems = new HashMap<OrderItemEntity, OrderItemEntity>();
final ListIterator<DiscreteOrderItemEntity> li = ((BundleOrderItemEntity) oi).getDiscreteOrderItems().listIterator();

while (li.hasNext()) {
    final DiscreteOrderItemEntity doi = li.next();
    final DiscreteOrderItemEntity savedDoi = (DiscreteOrderItemEntity) orderItemService.saveOrderItem(doi);
    savedOrderItems.put(doi, savedDoi);
    li.remove();
}

((BundleOrderItemEntity) oi).getDiscreteOrderItems().addAll(doisToAdd);
final BundleOrderItemEntity savedBoi = (BundleOrderItemEntity) orderItemService.saveOrderItem(oi);
savedOrderItems.put(oi, savedBoi);

我将4个项目放入HashMap。当我调试时,即使size为4,它也只显示3个元素:

debugging session

这是它包含的元素列表。

{DiscreteOrderItemEntity@1c29ef3c=DiscreteOrderItemEntity@41949d95, DiscreteOrderItemEntity@2288b93c=DiscreteOrderItemEntity@2288b93c, BundleOrderItemEntity@1b500292=BundleOrderItemEntity@d0f29ce5, DiscreteOrderItemEntity@9203174a=DiscreteOrderItemEntity@9203174a}

可能是什么问题?

2 个答案:

答案 0 :(得分:14)

Hashmaps处理冲突

由于HashMap仅由16个桶组成,因此元素的哈希值必须减少到跨越 0 15 之间的数字(例如hash % 16)。因此,两个元素可能位于同一个桶中(相同的HashMapNode)。

您可以检查每个HashMapNode以找出哪个包含两个元素。

答案 1 :(得分:1)

该机制被解释为enrico.bacis,有一个例子可以重现它:

public class TestJava {
    static class TT {
        private String field;
        @Override
        public int hashCode() {
            return 1;
        }
    }
    public static void main(String[] args) {
        Map<TT, String> test = new HashMap<>();
        TT t1 = new TT();
        TT t2 = new TT();
        test.put(t1, "test2");
        test.put(t2, "test2");
        test.put(null, "test2");
        test.put(null, "test2");

        System.out.println(test.toString());
        System.out.println(test.size());
    }
}

在那里,我们覆盖hashCode,硬代码返回 1 TT的所有对象都将返回相同的hashCode 1

我们可以深入研究HashMap.java

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
               boolean evict) {

我们可以找到当我们将键/值对放入HashMap时,它会通过对象的哈希码计算hash number来定位元素在哈希表中的位置。

因此,如果对象哈希码相同,它们将存储在哈希表的同一个桶中。但是这些confilct元素仍然会被存储,因为它们的关键不一样。