.Net эквивалент Java System.identityHashCode () - PullRequest
0 голосов
/ 13 ноября 2018

Java System.identityHashCode()

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

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

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

[...] мусорные объекты легко утилизируются, а адресное пространство повторно. Столкновения возникают в результате повторного использования адресного пространства. Если оригинал объект остается живым (не GCed), тогда вы не столкнетесь с этим проблема.

Источник

В .Net существует RuntimeHelpers.GetHashCode(), который удовлетворяет первому условию, но не второму:

Обратите внимание, что GetHashCode всегда возвращает идентичные хеш-коды для одинаковых ссылок на объекты. Однако обратное неверно: одинаковые хеш-коды не указывают на равные ссылки на объекты. Конкретное значение хеш-кода не является уникальным для конкретной ссылки на объект; различные ссылки на объекты могут генерировать идентичные хэш-коды.

Так есть ли что-нибудь похожее на identityHashCode() Java в .Net?

Edit:

Было высказано предположение, что это то же самое, что и Адрес памяти объекта в C # , которым он не является, поскольку адрес памяти не может использоваться здесь (исключительно), так как управление памятью перемещает объекты, следовательно адрес может измениться в течение срока службы объекта.

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

В настоящее время Java Object#hashCode() и System#identifyHashCode() do not обеспечивают возвращение уникальных значений.Уже есть вопросы по этому поводу, и this является примером.

Вы упомянули сообщение об ошибке, в котором говорится, что столкновение произошло , потому что объекты были собраны мусором, итот же адрес памяти используется повторно.Однако изменение того же тестового примера может доказать обратное:

List<Object> allObjs = new ArrayList<>(); // Used to prevent GC
Set<Integer> hashes = new HashSet<Integer>(1024);

int colls = 0;
for (int n = 0; n < 100000; n++)
{
    Integer obj = new Integer(88);
    allObjs.add(obj); // keep a strong reference to prevent GC
    int ihash = System.identityHashCode(obj);
    Integer iho = Integer.valueOf(ihash);
    if (hashes.contains(iho))
    {
        System.err.println("System.identityHashCode() collision!");
        colls++;
    }
    else
    {
        hashes.add(iho);
    }
}

System.out.println("created 100000 different objects - "
        + colls
        + " times with the same value for System.identityHashCode()");

System.out.println("Size of all objects is " + allObjs.size());
System.out.println("Size of hashset of hash values is " + hashes.size());

Результат:

System.identityHashCode() collision!
System.identityHashCode() collision!
System.identityHashCode() collision!
created 100000 different objects - 3 times with the same value for System.identityHashCode()
Size of all objects is 100000
Size of hashset of hash values is 99997

В связанном вопросе SO также упоминалось, что в некоторых реализациях JRE скоростьстолкновение значительно уменьшено .Однако кажется, что ни одна реализация не смогла предотвратить все коллизии.Следовательно, нет способа обеспечить уникальность хеш-кодов даже в Java.

Поэтому не стоит просто верить, основываясь на одном источнике.Человек, который комментирует это, также является просто членом команды Oracle, и он или она, скорее всего, не тот, кто разрабатывает это.

В C # и Java вам придется создать свой собственный генератор уникальных чиселкакой-то.Таким образом, решение , предоставленное NPras, похоже, делает это для .NET.

0 голосов
/ 13 ноября 2018

Я хотел бы отослать вас к следующему ответу от Эрика Липперта (который был частью команды разработки и компиляции языка C #), где он предложил использовать ObjectIDGenerator.

Чтобы сгенерировать уникальные идентификаторы для объектов, вы можете использовать метко названное ObjectIDGenerator, которое мы вам предоставим

Просмотр справочного источника (хорошо, что теперь они открыли фреймворк), он использует RuntimeHelpers.GetHashCode(), но также обрабатывает потенциальные столкновения, сохраняя ссылки отдельно.

Обратите внимание на его предупреждение о времени жизни объекта. Если он вам нужен для временных объектов, он предложил вам переопределить генератор, который теперь намного проще, чем доступ к источнику.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...