Возможно ли иметь один и тот же хэш-код для разных строк с использованием java-функции hashcode? или если это возможно, то какой% его возможности?
Может ли Java hashCode выдавать одинаковое значение для разных строк?
Ответ 1
Явный хэш-код Java - 32 бит. Количество возможных цепочек хэшей бесконечно.
Итак, да, будут столкновения. Процент бессмыслен - существует бесконечное количество элементов (строк) и конечное число возможных хэшей.
Ответ 2
ДА. Много.
Посмотрите на следующую пару
- "FB" и "Ea"
может возвращать один и тот же хэш-код, даже если символы в нем не совпадают.
В основном это сумма символов в строке, умноженная на целое число.
Ответ 3
Да, это вполне возможно. Вероятность строки (или какого-либо другого типа объекта - просто предполагая, что вы будете использовать строки в этом примере), имеющие тот же хэш-код, что и некоторая другая строка в коллекции, зависит от размера этой коллекции (если предположить, что все строки в эта коллекция уникальна). Вероятности распределяются следующим образом:
- С набором размеров ~ 9 000 у вас будет 1% -ный шанс, что две строки столкнутся с хешем в наборе
- При наборе размера ~ 30 000 у вас будет 10% вероятность того, что две строки столкнутся с хешем в наборе
- С набором размеров ~ 77 000 у вас будет 50% вероятность того, что две строки столкнутся с хешем в наборе
Сделанные предположения:
- Функция hashCode не имеет смещения
- Каждая строка в вышеупомянутом наборе уникальна
Этот сайт четко объясняет: http://eclipsesource.com/blogs/2012/09/04/the-3-things-you-should-know-about-hashcode/ (Посмотрите на "второе, что вы должны знать" )
Ответ 4
если это возможно, то каков% его возможности?
Это не особо важный вопрос.
Однако, если в функции hashcode
нет системного смещения, вероятность того, что любые две разные (не равные) строки имеют один и тот же хэш-код, будет равна 1 в 2 ^ 32.
Это предполагает, что строки выбираются случайным образом из множества всех возможных значений String. Если вы ограничите набор различными способами, вероятность будет отличаться от указанного выше числа. (Например, существование столкновения "FB" / "Ea" означает, что вероятность столкновения в множестве всех двух буквенных строк выше нормы.)
Еще одна вещь, которую следует отметить, состоит в том, что вероятность 2 ^ 32 различных строк, выбранных случайным образом (из гораздо большего несмещенного набора строк), не имеющих хэш-коллизий, исчезающе мала. Чтобы понять, почему, прочитайте страницу Википедии на Парад дня рождения. На самом деле, единственный способ, которым вы не получите никаких хэш-коллизий в наборе из 2 ^ 32 разных строк, - это выбрать или сгенерировать строки. (И даже формирование набора путем выбора случайно сгенерированных строк будет стоить дорогостоящим.)
Ответ 5
Это не будет напрямую отвечать на ваш вопрос, но я надеюсь, что это поможет.
Ниже приведен исходный код java.lang.String
.
/**
* Returns a hash code for this string. The hash code for a
* <code>String</code> object is computed as
* <blockquote><pre>
* s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
* </pre></blockquote>
* using <code>int</code> arithmetic, where <code>s[i]</code> is the
* <i>i</i>th character of the string, <code>n</code> is the length of
* the string, and <code>^</code> indicates exponentiation.
* (The hash value of the empty string is zero.)
*
* @return a hash code value for this object.
*/
public int hashCode() {
int h = hash;
int len = count;
if (h == 0 && len > 0) {
int off = offset;
char val[] = value;
for (int i = 0; i < len; i++) {
h = 31*h + val[off++];
}
hash = h;
}
return h;
}
Ответ 6
Да, две строки могут иметь один и тот же хэш-код. Если вы посмотрите на статью Wikipedia, вы увидите, что оба "FB"
и "Ea"
имеют одинаковый хэш-код. В контракте метода ничего нет, говоря, что hashCode()
следует использовать для сравнения для равенства, вы хотите использовать equals()
для этого.
Так как Java 1.2, String реализует hashCode()
с использованием алгоритма суммирования продукта по всему тексту строки.
Ответ 7
Да, по определению концепции голубя-дыры, две разные строки могут создавать один и тот же хэш-код, и код всегда должен записываться для удовлетворения таких условий (как правило, не прерывая).
Ответ 8
Процент коллизий для случайных строк должен быть минимальным. Однако, если вы используете хэш-строки из внешних источников, злоумышленник может легко создать сотни тысяч строк, имеющих один и тот же хэш-код. В java HashMap все они будут сопоставлены с одним ведром и эффективно превратят карту в связанный список. Тогда время доступа к карте будет пропорционально размеру карты вместо константы, что приведет к атаке отказа в обслуживании.
См. эту страницу в Эффективные атаки DoS против Plattforms для веб-приложений для получения дополнительной информации о ссылках на презентацию.
Ответ 9
Да, это возможно, потому что один из контрактов между методом equals() и hashCode() класса Object равен.......... Если два объекта не равны в соответствии с методом equals(), то гарантии нет что их hashCode будет таким же, hashCode может/не может быть равным. то есть, если obj1.equals(obj2) возвращает false, то obj1.hashCode() == obj2.hashCode() может/не может возвращать true. Пример:
String str1 = "FB";
String str2 = "Ea";
System.out.println(str1.equals(str2));// false
System.out.println(str1.hashCode() == str2.hashCode()); // true
Ответ 10
//Вы можете запустить приведенный ниже код с помощью -Xmx2100m и получить несколько результатов, достаточных для заполнения консоли
'
import java.util.HashMap;
public class TestHashCollision {
public static void main(String[] args) {
final String TEXT = "was stored earlier had the same hash as";
HashMap<Integer,String> hs=new HashMap<>();
long t1=System.currentTimeMillis();
long t2=System.currentTimeMillis();
for(long l=0;l<Long.MAX_VALUE;l++) {
String key="d"+l;
if(hs.containsKey(key.hashCode())) {
System.out.println("'"+hs.get(key.hashCode())+"' "+TEXT+" '"+key+"'");//System.exit(0);
} else {
hs.put(key.hashCode(),key);
}
t2=System.currentTimeMillis();
if(t2-t1>10000) {
t1=System.currentTimeMillis();
System.out.println("10 seconds gone! size is:"+hs.size());
}
}
System.out.println("Done");
}
}
'