如何为android中的字符串输入生成唯一的哈希码...?
Posted
技术标签:
【中文标题】如何为android中的字符串输入生成唯一的哈希码...?【英文标题】:How to generate a unique hash code for string input in android...? 【发布时间】:2011-09-01 12:22:39 【问题描述】:我想为 android 中的字符串生成一个唯一的哈希码。 是否有任何预定义的库,或者我们必须手动生成。请任何知道的人提供链接或代码。
【问题讨论】:
字符串的内置 hashCode 怎么样? 唯一哈希码?为什么?你怎么会认为这是可能的? 请详细说明。唯一的哈希码是不可能的(除非它们可以有无限长),因为可能的字符串是无限的。 那是完全错误的。我能想到五种方法来创建一个独特的哈希码。这一切都从重写 hashCode () 函数开始。无论如何,最后一条评论有点过于简单化了:如果在足够大的域上使用强大的生成器创建散列,那么发生冲突的机会可能会非常小。如果您覆盖 hashCode 以使用线程安全增量器,则您可以拥有唯一值。但是,大多数时候,如果正确实施,它只是无关紧要概率。 您不知道 OP 的上下文是什么。完全不知道。假设当他说“独特”时,他并不意味着这是一个巨大的延伸。无论如何,挑战仍然存在:告诉我们如何做。 【参考方案1】:这取决于你的意思:
如前所述,String.hashCode()
为您提供 32 位哈希码。
如果您想要(比如说)一个 64 位哈希码,您可以自己轻松实现它。
如果您想要字符串的加密哈希,Java 加密库包括 MD5、SHA-1 等的实现。您通常需要将字符串转换为字节数组,然后将其提供给哈希生成器/摘要生成器。例如,请参阅@Bryan Kemp 的回答。
如果您想要一个保证唯一哈希码,那么您就不走运了。哈希和哈希码是非唯一的。
长度为 N 的 Java 字符串具有65536 ^ N
可能的状态,并且需要一个带有16 * N
位的整数来表示所有可能的值。如果你写了一个哈希函数,它产生的整数范围更小(例如,小于16 * N
位),你最终会发现多个字符串哈希到同一个整数的情况;即哈希码不能是唯一的。这称为Pigeonhole Principle,并且有一个直接的数学证明。 (你不能打数学赢!)
但是,如果“可能是唯一的”具有非常小的非唯一性机会是可以接受的,那么加密哈希是一个很好的答案。数学将告诉您哈希必须有多大(即多少位)才能实现给定(足够低)的非唯一性概率。
【讨论】:
64 位哈希码:如果您想要一个 64 位哈希码,为了完整性,来自***.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
【讨论】:
以上是关于如何为android中的字符串输入生成唯一的哈希码...?的主要内容,如果未能解决你的问题,请参考以下文章