【问题标题】:How to generate a unique hash code for string input in android...?如何为android中的字符串输入生成唯一的哈希码...?
【发布时间】:2011-09-01 12:22:39
【问题描述】:

我想为 android 中的字符串生成一个唯一的哈希码。 是否有任何预定义的库,或者我们必须手动生成。请任何知道的人提供链接或代码。

【问题讨论】:

  • 字符串的内置 hashCode 怎么样?
  • 唯一哈希码?为什么?你怎么会认为这是可能的?
  • 请详细说明。唯一的哈希码是不可能的(除非它们可以有无限长),因为可能的字符串是无限的。
  • 那是完全错误的。我能想到五种方法来创建一个独特的哈希码。这一切都从重写 hashCode () 函数开始。无论如何,最后一条评论有点过于简单化了:如果在足够大的域上使用强大的生成器创建散列,那么发生冲突的机会可能会非常小。如果您覆盖 hashCode 以使用线程安全增量器,则您可以拥有唯一值。但是,大多数时候,如果正确实施,它只是无关紧要概率。
  • 您不知道 OP 的上下文是什么。完全不知道。假设当他说“独特”时,他并不意味着这是一个巨大的延伸。无论如何,挑战仍然存在:告诉我们如何做。

标签: java android hash hashmap


【解决方案1】:

这取决于你的意思:

  • 如前所述,String.hashCode() 为您提供 32 位哈希码。

  • 如果您想要(比如说)一个 64 位哈希码,您可以自己轻松实现它。

  • 如果您想要字符串的加密哈希,Java 加密库包括 MD5、SHA-1 等的实现。您通常需要将字符串转换为字节数组,然后将其提供给哈希生成器/摘要生成器。例如,请参阅@Bryan Kemp 的回答。

  • 如果您想要一个保证唯一哈希码,那么您就不走运了。哈希和哈希码是非唯一的。

长度为 N 的 Java 字符串具有65536 ^ N 可能的状态,并且需要一个带有16 * N 位的整数来表示所有可能的值。如果你写了一个哈希函数,它产生的整数范围更小(例如,小于16 * N 位),你最终会发现多个字符串哈希到同一个整数的情况;即哈希码不能是唯一的。这称为Pigeonhole Principle,并且有一个直接的数学证明。 (你不能打数学赢!)

但是,如果“可能是唯一的”具有非常小的非唯一性机会是可以接受的,那么加密哈希是一个很好的答案。数学将告诉您哈希必须有多大(即多少位)才能实现给定(足够低)的非唯一性概率。

【讨论】:

  • 64 位哈希码:如果您想要一个 64 位哈希码,为了完整性,来自stackoverflow.com/questions/1660501/… 中的 sfussenegger
  • 那么,一个32位的hash只能唯一标识2个字符的String吗?
  • 基本上......是的。 (假设字符 == 任意 char 值。如果字符表示 Unicode 代码点...或(比如)ASCII 代码点,情况会变得更复杂。)
【解决方案2】:

这是我用来创建消息摘要哈希的类

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Sha1Hex {

    public String makeSHA1Hash(String input)
            throws NoSuchAlgorithmException, UnsupportedEncodingException
        {
            MessageDigest md = MessageDigest.getInstance("SHA1");
            md.reset();
            byte[] buffer = input.getBytes("UTF-8");
            md.update(buffer);
            byte[] digest = md.digest();

            String hexStr = "";
            for (int i = 0; i < digest.length; i++) {
                hexStr +=  Integer.toString( ( digest[i] & 0xff ) + 0x100, 16).substring( 1 );
            }
            return hexStr;
        }
}

【讨论】:

    【解决方案3】:
    String input = "some input string";
    int hashCode = input.hashCode();
    System.out.println("input hash code = " + hashCode);
    

    【讨论】:

    • @Vladimir - 根据定义,没有哈希码被定义为唯一的! Hashcode需要很好的分布,唯一性的想法是对OP的错误理解。
    • 如果哈希码是唯一的,那将是一种非常糟糕的压缩算法。
    • 例如尝试 "Z@S.ME" 和 "Z@RN.E" 它们在使用 hashCode 时具有相同的哈希值;)
    • @Simon,刚刚在 .NET 中运行了您的示例,因为我很好奇。它们必须具有不同的基本哈希算法,因为它们在那里不完全匹配。 dotnetfiddle.net/6YJRpV
    • 也许 OP 所说的 unique 的意思是:unique-for-a-given-input-string(不应该为同一个字符串生成两个哈希)。
    【解决方案4】:

    我使用它作为我的 EhCacheManager 内存映射中的密钥进行测试 ....

    我想它更干净

       /**
         * Return Hash256 of String value
         *
         * @param text
         * @return 
         */
        public static String getHash256(String text) {
            try {
                return org.apache.commons.codec.digest.DigestUtils.sha256Hex(text);
            } catch (Exception ex) {
                Logger.getLogger(HashUtil.class.getName()).log(Level.SEVERE, null, ex);
                return "";
            }
        }
    

    我正在使用 maven,但这是 jar commons-codec-1.9.jar

    【讨论】:

      【解决方案5】:

      您可以使用此代码为给定字符串生成 has 代码。

      int hash = 7;
      for (int i = 0; i < strlen; i++) {
          hash = hash*31 + charAt(i);
      }
      

      【讨论】:

      • 你为什么从 7 点开始?
      【解决方案6】:

      对我来说很有效

         public static long getUniqueLongFromString (String value){
             return  UUID.nameUUIDFromBytes(value.getBytes()).getMostSignificantBits();
          }
      

      【讨论】:

        【解决方案7】:

        几行java代码。

        public static void main(String args[]) throws Exception{
               String str="test string";
               MessageDigest messageDigest=MessageDigest.getInstance("MD5");
               messageDigest.update(str.getBytes(),0,str.length());
               System.out.println("MD5: "+new BigInteger(1,messageDigest.digest()).toString(16));
        }
        

        【讨论】:

          【解决方案8】:

          我们来看看股票的hashCode()方法:

          public int hashCode() {
              int h = hash;
              if (h == 0 && count > 0) {
                  for (int i = 0; i < count; i++) {
                      h = 31 * h + charAt(i);
                  }
                  hash = h;
              }
              return h;
          }
          

          上面的代码块来自 java.lang.String 类。如您所见,它是一个 32 位哈希码,如果您在小规模数据上使用它就足够公平了。如果您正在寻找超过 32 位的哈希码,您可能需要查看此链接: http://www.javamex.com/tutorials/collections/strong_hash_code_implementation.shtml

          【讨论】:

            猜你喜欢
            • 2015-05-22
            • 2013-10-07
            • 2014-12-31
            • 1970-01-01
            • 2021-01-01
            • 2013-09-17
            • 1970-01-01
            • 2012-03-07
            • 1970-01-01
            相关资源
            最近更新 更多