Java TreeMap содержит ключ, но вызов containsKey возвращает false (даже ключ является точно таким же неизменным объектом)
Почему можно зациклить keySet
TreeMap и получение .containsKey == false
?
for (Object thisObject : map.keySet()) {
if (!map.containsKey(thisObject)) {
System.out.println("This line should be never reached.");
}
}
После большого количества разных итераций и вызовов эта строка получает удар. map.get(thisObject)
вернется null
, Но отладка показывает, что ключ (та же ссылка, значение и хеш) и фактическое значение находятся на карте. Карта небольшая (25 элементов) TreeMap<Long, Double>
ОБНОВИТЬ:
Как и предполагал rgettman, существует пользовательская сортировка. Comparator
используется при построении TreeMap (не видел его, потому что он был создан из другого класса). Этот компаратор был просто (я думаю) копия вставлена отсюда
Изменение Comparator
:
public int compare(Object a, Object b) {
if((Double)base.get(a) > (Double)base.get(b)) {
return 1;
} else if((Double)base.get(a) == (Double)base.get(b)) {
return 0;
} else {
return -1;
}
}
в
...
} else if(base.get(a).equals(base.get(b))) {
return 0;
...
устраняет проблему Причина, по которой эта проблема появилась сразу после миллионов операций, заключалась в том, что не было случаев, когда на карте было бы два одинаковых значения для двух разных ключей, поскольку это очень маловероятно в контексте.
Так что в:
25151l, 1.7583805400614032
24827l, 1.7583805400614032
это терпит неудачу.
Спасибо за вашу помощь!
3 ответа
Вы должны были внести изменения в поддержку entrySet()/Map.Entry
тем самым меняются порядки клавиш, что приводит к неудачному поиску containsKey
,
Большинство этих классов реализации опираются как на hashCode(), так и equals(), которые поддерживаются и корректны.
Если у вас действительно одинаковый хеш-код из объектов, попробуйте найти совпадение. Ответ, предложенный мной, заключается в том, что они не совпадают.
В противном случае сценарий должен быть достаточно маленьким, чтобы вы могли опубликовать объекты и / или их соответствующий хэш-код и метод equals.
Я только что выполнил код, этот случай вернул мне истину.
TreeMap<Long,Double> otm = new TreeMap<Long, Double>();
otm.put(1L, 1.0);
otm.put(2L, 2.0);
for (Object thisObject : otm.keySet()) {
System.out.println(otm.containsKey(thisObject));
}
Можете ли вы дать нам данные, которые вы вводите в TreeMap. Спасибо
Это реализация containsKey (ключ объекта) из JavaDocs
ContainsKey
логическое содержит ключ (объектный ключ)
Возвращает true, если эта карта содержит отображение для указанного ключа.
Более формально, возвращает true тогда и только тогда, когда эта карта содержит отображение для ключа k, такого что (key==null? K == null: key.equals (k)). (Может быть не более одного такого отображения.)
Параметры:
key - key whose presence in this map is to be tested Returns: true if this map contains a mapping for the specified key Throws: ClassCastException - if the key is of an inappropriate type for this map (optional) NullPointerException - if the specified key is null and this map does not permit null keys (optional
Надеюсь, это поможет.