2016-04-15 4 views
4

Я определяю мой класс, как:Равномерное распределение хэш-код()

final class Key<T extends Comparable<T>> { 
    private final T q; 
    private final T o; 
    public Key(T q1, T o1) { 
     q = q1; 
     o = o1; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if(obj != null && obj instanceof Key) { 
      Key<T> s = (Key<T>)obj; 
      return q.equals(s.q) && o.equals(s.o); 
     } 
     return false; 
    } 

    @Override 
    public int hashCode() { 
     return Objects.hash(q,o); 
    } 
} 

Я также определить массив содержать ключ объекта. Например:

Object arr[] = new Object[100]; 
Key<String> k = new Key<>("a","b"); 
int h = k.hashcode(); 
... 
arr[h+i % h] = k; //i from 1 to 10 for example 

Проблема заключается в том, что хэш-код() может возвращать отрицательное значение, так

arr[h+i % h] = k; 

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

@Override 
     public int hashCode() { 
      return (Objects.hash(q,o)&0x7FFFFFFF); 
     } 

Так что, если я делаю это так, делает равномерное распределение хэш-код() быть изменено или нет? Я имею в виду, что вероятность иметь одно и то же значение от двух разных объектов будет увеличена или нет?

+0

Как вы можете создать объект ключа в качестве ключа . Он должен давать ошибку компилятора как неправильное количество аргументов для типа Key Roshan

+0

Да, моя ошибка. Я также отредактировал его. Спасибо – nd07

+0

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

ответ

2

Object.hash() имеет очень простой хэш-код, который не является особенно однородным для простых примеров. например Objects.hash («B», «B») и Objects.hash («A», «a») имеют одинаковый хэш-код. (И BTW достаточно просто, чтобы я мог это сделать в своей голове)

Также между Objects.hashCode("a", "a") и Objects.hashCode("z", "z") находится между 4065 и 4865, что не выглядит особенно однородным, особенно для более высоких бит.

В этом контексте, я думаю, вы можете сказать, что вы не делаете ничего хуже.

+0

Если это так. в каком направлении лучше избегать отрицательного значения hashcode() 1. как указано выше 2. избегайте отрицательного значения на этом этапе: arr [h + i% h] = k. Я имею в виду, что я использую Math.abs (h + i% h) для преобразования в положительное значение. – nd07

+0

@ nd07 Вы хотите избежать «Math.abs» здесь, так как это может вернуть отрицательное число o_O. Лучше использовать '(hash & 0x7FFF_FFFF)% buckets'. Примечание: 'Math.abs (Integer.MIN_VALUE) == Integer.MIN_VALUE', о котором вы вряд ли узнаете в течение длительного времени. –

+1

да, спасибо за вашу поддержку – nd07

2

Пожалуйста, посмотрите, чтобы Murmurhash и MurmurHash - what is it? К счастью Google гуавы уже готовые реализации для этого.

гуавы путь, как показано ниже, например Мы имеем следующие классы

import com.google.common.hash.HashCode; import com.google.common.hash.HashFunction; import com.google.common.hash.Hashing;

с помощью описанных выше классов у меня есть метод для создания хэш-код, как показано ниже

/** 
    * getMurmur128Hash. 
    * 
    * @param content 
    * @return HashCode 
    */ 
    public static HashCode getMurmur128Hash(String content) { 
     final HashFunction hf = Hashing.murmur3_128(); 
     final HashCode hc = hf.newHasher().putString(content, Charsets.UTF_8).hash(); 
     return hc; 
    } 
    /** 
    * getAbsMurmur128HashAsLongVal. 
    * 
    * @param content 
    * @return Long Absolute value of Long for the HashCode. 
    */ 
    public static Long getAbsMurmur128HashAsLongVal(String content) { 
     return Math.abs(getMurmur128Hash(content).asLong()); 
    }