6

我写了一个哈希图并用键/值条目填充它。值是对象。该地图包含至少 10,000 个条目。稍后当我想使用某个键获取值时,地图似乎找不到这个条目。这太奇怪了。即使每次它在不同的条目上失败。我能做些什么来解决这个问题?我正在使用 weblogic 作为服务器。我应该使用任何环境值吗?

4

4 回答 4

14

以下是一些可能导致条目“丢失”的情况:

  • 在您的关键对象上错误地实现了 equals / hashcode 方法。这两种方法需要遵守“契约”才能使哈希表正常工作。最重要的属性是:

    key1.equals(key2) IMPLIES key1.hashcode() == key2.hashcode
    
  • 在映射中使用键时更改的可变键对象。特别是,如果 key 改变导致 key 的 hashcode 改变,它就会丢失。(在这种情况下,如果您遍历整个地图,条目将显示出来。但是使用 has lookup 的地图操作不会找到它们......因为它们位于错误的哈希链上。)

    最安全的方法是使用不可变的密钥类。

  • 在没有正确同步的多线程应用程序中使用映射。这可能会导致地图数据结构损坏,这可能表现为丢失的条目。

  • 您不知道的应用程序的其他一些部分正在删除条目。


声明/声明您必须覆盖equals并且hashcode是/不正确的答案。在某些情况下Object,这些方法的实现正是所需要的。您需要做的是确保:

  1. 您正在使用用例要求的适当形式的密钥相等,并且
  2. equalshashcode遵守“合同”。

我能做些什么来解决这个问题?

我建议进行代码检查以检查上述问题。

调试是另一种选择。例如,您可以查看是否可以在错误的哈希链上找到丢失的条目。但是,我怀疑这种方法可能有点“碰巧”。

我正在使用 weblogic 作为服务器。

不相关......除非您碰巧使用由 Weblogic 而不是 J2SE 实现的某些 Map 实现类。(查看对象的类名。)

我应该使用任何环境值吗?

不,这无济于事

于 2013-01-16T03:37:41.727 回答
3

一种可能的情况是:

如果 key 是类的实例并且该类没有覆盖 equals/hashcode 方法,则 get 方法可能返回 false。

于 2013-01-16T03:23:40.023 回答
3

如果您的密钥是可变的,那么以改变其哈希值的方式改变密钥将导致查找失败。

例如,假设您有以下可变类:

public class MyKey {
    private int value;
    public void setValue(int value) {
        this.value = value;
    }
    public int hashCode() {
        return value;
    }
    public boolean equals(Object obj) {
        //...
    }
}

那么这是可能的:

MyKey key = new MyKey();
key.setValue(1);

Map<MyKey, String> map = new HashMap<MyKey, String>();
map.put(key, "Hello");

System.out.println("map contains: " + map.get(key)); // "map contains: Hello"
key.setValue(2);
System.out.println("map contains: " + map.get(key)); // "map contains: "
于 2013-01-16T03:36:54.240 回答
0

扩展 Nambari 的答案:

如果您使用不覆盖 equals 和 hashCode 作为键的类,则相等性基于对象相等性(例如:相同的对象地址,不同的内容)。这与您不能将字符串与 == 进行比较的原因相同。

    class Key {
       public String k;
       public Key(String k) { this.k = k; }

       /*
       //with this it would work.
       public boolean equals(Object o) { 
            if (o instanceof Key) return ((Key)o).k.equals(k);
            return false;
       }

       public int hashCode() {
            return k.hashCode();
       }
       */
    }

    map.put(new Key("a"),"test");
    map.get(new Key("a"));  // does NOT return "test" because key is another instance.
于 2013-01-16T03:28:38.923 回答