Столкновение Java Map :: hashCode () - почему? - PullRequest
4 голосов
/ 03 сентября 2010

Следующий код приводит к тому, что для двух карт генерируется одинаковый хеш-код, есть идеи?


import java.util.HashMap;
import java.util.Map;

public class Foo
{
    @SuppressWarnings("unchecked")
    public static void main (String[] args)
    {
        Map map;

        map = new HashMap();

        map.put("campaignId", 4770L);
        map.put("location", "MINI_PROFILE");
        map.put("active", "true");
        map.put("lazy", true);

        System.out.println(map.hashCode());

        map = new HashMap();

        map.put("campaignId", 4936L);
        map.put("location", "MINI_PROFILE");
        map.put("active", "true");
        map.put("lazy", false);

        System.out.println(map.hashCode());


    }
}

Результат:

-1376467648
-1376467648

Простого изменения имен ключей достаточно, чтобы код генерировал два разных хеш-кода.

Ответы [ 4 ]

9 голосов
/ 03 сентября 2010

Просто совпадение, я подозреваю ... есть связанный , чтобы быть коллизиями, и в этом случае похоже, что соответствующие различные биты в первом значении фактически теряются.

Однако это не должно иметь никакого значения - все, что использует хеш-коды , должно справляться с коллизиями.

РЕДАКТИРОВАТЬ: Это просто способ вычисления хэшей.Этот код показывает, что происходит:

import java.util.*;

public class Test
{
    @SuppressWarnings("unchecked")
    public static void main (String[] args)
    {
        AbstractMap.SimpleEntry[] entries = {
            new AbstractMap.SimpleEntry("campaignId", 4770L),
            new AbstractMap.SimpleEntry("campaignId", 4936L),
            new AbstractMap.SimpleEntry("lazy", true),
            new AbstractMap.SimpleEntry("lazy", false)
        };
        for (AbstractMap.SimpleEntry entry : entries) {
            System.out.println(entry + ": " + entry.hashCode());
        }
    }
}

Результаты:

campaignId=4770: -1318251287
campaignId=4936: -1318251261
lazy=true: 3315643
lazy=false: 3315617

Таким образом, в одной паре первая карта имеет хэш 26 меньше , чем вторая карта,а в другой паре первая карта имеет хеш на 26 больше , чем вторая карта.

AbstractMap просто суммирует значения хеша (один из способов убедиться, что порядок не имеет значения), поэтому двав конечном итоге с тем же хеш-кодом.

Это действительно до Boolean.hashCode(), который выглядит так:

return value ? 1231 : 1237;

... и Long.hashCode(), который выглядит так:

return (int)(value ^ (value >>> 32));

Учитывая значения, которые они случайно выбрали в Boolean.hashCode(), если ваши long значения расположены только на 26 (или на 26 * 2 ^ 32), то вы столкнетесь с тем же.

6 голосов
/ 03 сентября 2010

Я думаю, что это просто совпадение. Из Javadoc для AbstractMap # hashCode ():

Хеш-код карты определяется как сумма хеш-кодов каждой записи в представлении entrySet () карты.

И для Entry # hashCode ():

Возвращает значение хэш-кода для этой записи карты. Хеш-код записи карты e определен так:

 (e.getKey()==null   ? 0 : e.getKey().hashCode()) ^
 (e.getValue()==null ? 0 : e.getValue().hashCode())

Таким образом, хэш-коды для карт основаны как на ключах, так и на значениях, содержащихся в карте. Вы просто испытываете странную ситуацию, когда две карты имеют одинаковый хэш-код без видимой причины.

3 голосов
/ 03 сентября 2010

Столкновения случаются.Фактически, вы можете переопределить hashCode (), чтобы он всегда возвращал 0 для каждого HashMap, и это было бы правильно (хотя это сделало бы множество структур медленными ).

0 голосов
/ 21 июня 2013

Это не совпадение.

Строковые объекты одинаковы в обоих.Тот же объект даст тот же хеш-код.

...