2015-04-29 2 views
-1

У меня есть часть кода, сгенерирующая подпись на C#, и для удобства я использовал hashcode, и это было хорошо.Как реализовать точный C# hashcode в Java

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

В настоящее время мне нужен только хэш-код int, double, string и bool. int и bool просты. реальная вещь, о которой я не могу думать простым способом, - это двойная и строка. моя среда всегда будет 64-битной. У меня есть источник в следующем:

строка:

 public override int GetHashCode() { 

#if FEATURE_RANDOMIZED_STRING_HASHING 
      if(HashHelpers.s_UseRandomizedStringHashing) 
      { 
       return InternalMarvin32HashString(this, this.Length, 0); 
      } 
#endif // FEATURE_RANDOMIZED_STRING_HASHING 

      unsafe { 
       fixed (char *src = this) { 
        Contract.Assert(src[this.Length] == '\0', "src[this.Length] == '\\0'"); 
        Contract.Assert(((int)src)%4 == 0, "Managed string should start at 4 bytes boundary"); 

#if WIN32 
        int hash1 = (5381<<16) + 5381; 
#else 
        int hash1 = 5381; 
#endif 
        int hash2 = hash1; 

#if WIN32 
        // 32 bit machines. 
        int* pint = (int *)src; 
        int len = this.Length; 
        while (len > 2) 
        { 
         hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27))^pint[0]; 
         hash2 = ((hash2 << 5) + hash2 + (hash2 >> 27))^pint[1]; 
         pint += 2; 
         len -= 4; 
        } 

        if (len > 0) 
        { 
         hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27))^pint[0]; 
        } 
#else 
        int  c; 
        char *s = src; 
        while ((c = s[0]) != 0) { 
         hash1 = ((hash1 << 5) + hash1)^c; 
         c = s[1]; 
         if (c == 0) 
          break; 
         hash2 = ((hash2 << 5) + hash2)^c; 
         s += 2; 
        } 
#endif 
#if DEBUG 
        // We want to ensure we can change our hash function daily. 
        // This is perfectly fine as long as you don't persist the 
        // value from GetHashCode to disk or count on String A 
        // hashing before string B. Those are bugs in your code. 
        hash1 ^= ThisAssembly.DailyBuildNumber; 
#endif 
        return hash1 + (hash2 * 1566083941); 
       } 
      } 
     } 

Я не уверен FEATURE_RANDOMIZED_STRING_HASHING (я предполагаю, что он не установлен, хотя), и отливка указатель здесь:

int* pint = (int *)src; 

в java не звучит просто.

для двойной:

public unsafe override int GetHashCode() { 
    double d = m_value; 
    if (d == 0) { 
     // Ensure that 0 and -0 have the same hash code 
     return 0; 
    } 
    long value = *(long*)(&d); 
    return unchecked((int)value)^((int)(value >> 32)); 
} 

тот же вопрос. есть литье, ссылка и разыменование указателя.

как я могу это сделать в java (нет собственного кода)?

+0

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

+0

@HenkHolterman ой действительно ?! я протестировал на своем столе по крайней мере, и я думаю, что строка должна быть только на основе контента. Можете ли вы посоветовать мне узнать, как я могу настроить собственный хэш-код (надеюсь, это просто извлечение из источника C#?)? – HuStmpHrrr

ответ

0

Интересно, если вы не делаете это более сложным, чем это должно быть со всем небезопасным сектором и указателями. Почему бы вам не начать с решения в java, а затем вернуть его обратно на C#.

Бьюсь об заклад, в сети есть множество решений для создания хэша на Java, а порт с java на C# должен быть тривиальным.

редактировать: На самом деле, я смотрел это для вас: Good Hash Function for Strings

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

В ответ на комментарий: Если вам нужна такая же функция между C# и Java, вам понадобится решение, которое не использует указатели. Это решение, вероятно, будет работать так же хорошо или в любом случае (потому что у компилятора больше свободы при его оптимизации) и, безусловно, будет более читаемым, поэтому, если вы хотите использовать это решение, перекодируйте его, чтобы сделать это без указателей, затем используйте его как в C# и Java.

Если вы не можете перекодировать его на своем основном языке - C#, вы, конечно, не сможете это сделать на Java.

Поддерживайте совместимость, обладая хорошей эксплуатационной защитой, если у вас нет достаточного количества модульных тестов, напишите их перед внесением любых изменений. Если вы протестируете существующие хеш-коды (кажется, вы их где-то сохраняете), вы можете быть в состоянии написать некоторые тесты C#, которые будут проверять как хэш-коды C#, так и Java, что также хорошо бы доказать, что ваши текущие усилия успешны.

+0

Я действительно использовал это в коде C#, и он используется. я хочу поддерживать совместимость – HuStmpHrrr