双向String散列函数

时间:2011-07-10 06:55:46

标签: java string hashcode

我想获得String的唯一数字表示。我知道有很多方法可以做到这一点,我的问题是你认为哪种方式最好?我不想有负数 - 所以java中的hashcode()函数不是那么好,虽然我可以覆盖它...但我宁愿不要因为我不那么自信而且不想意外打破了一些东西。

My Strings都是语义网URIS。数字表示的原因是,当我在页面上显示URI的数据时,我需要将某些内容传递给查询字符串或放入我的javascript中的各个字段。当URI作为URI中的值时,URI本身太笨重并且看起来很糟糕。

基本上我想要一个名为Resource的类,它看起来像这样

Resource{
  int id;
  String uri;
  String value; // this is the label or human readable name

  // .... other code/getters/setters here

  public int getId(){
    return id = stringToIntFunction();
  }

  private int stringToIntFunction(String uri){
  // do magic here
  }
}

如果出现以下情况,您能否建议执行此操作的功能:

  1. 必须是双向的,也就是说你也可以从数值
  2. 中恢复原始字符串
  3. 不一定是双向
  4. 还有其他重要问题我不考虑吗?

5 个答案:

答案 0 :(得分:12)

如果你想要它是可逆的,那你就麻烦了。哈希设计是单向的。

特别是,假设int有32位信息,而char有16位信息,则需要可逆性意味着你只能拥有零个,一个或两个字符的字符串(和即使这是假设您很乐意将“”编码为“\ 0 \ 0”或类似的东西)。当然,这是假设你没有任何存储空间。如果你可以使用存储,那么只需按顺序存储数字......例如:

private int stringToIntFunction(String uri) {
    Integer existingId = storage.get(uri);
    if (existingId != null) {
        return existingId.intValue();
    }
    return storage.put(uri);
}

这里storage.put()会在内部增加一个计数器,将URI存储为与该计数器值相关联,然后返回它。我的猜测是,这不是你所追求的。

基本上,为了执行可逆加密,我使用标准加密库,首先将字符串转换为二进制格式(例如使用UTF-8)。我希望结果是byte[]

如果必须是可逆的,我会考虑只取正常hashCode()结果的绝对值(但将Integer.MIN_VALUE映射到特定的,因为它的绝对值不能表示为int)。

答案 1 :(得分:7)

哈希只是一种方式(这是它们具有固定长度的原因的一部分,无论输入大小如何)。如果你需要双向,你会看到类似Base64编码的东西。

为什么你不能有负数? URI来自哪里?他们在数据库中吗?为什么不使用数据库密钥ID?如果它们不在数据库中,您是否可以在给定一组变量/参数的情况下为用户生成它们? (因此查询字符串只包含诸如foo = 1& bar = 2之类的内容,并且您在服务器或JavaScript端生成URL)

答案 2 :(得分:3)

考虑到上面所做的所有重做(散列函数是单向),我会选择2种可能的解决方案:

  • 使用一些加密函数来获取代表您的URL的长字符串(您将获得类似 - > param = 456ab894ce897b98f(这可能会更长和/或更短,具体取决于URL)。例如,请参阅DES加密或{ {3}}。
  • 跟踪数据库中的URL(也可以是简单的基于文件的数据库,如SQLite)。那么你将有效地获得一个uint< => URL等价。

答案 3 :(得分:2)

“唯一表示”意味着Java提供的string.hashcode将毫无用处 - 您很快就会遇到两个共享相同哈希码的URI。

任何双向方案都会导致一个笨重的字符串 - 除非您将URI存储在数据库中并使用记录ID作为唯一标识符。

就单向而言 - MD5哈希比简单哈希码更加独特(但绝不是唯一的) - 但根据你的定义可能会“笨拙”!

答案 4 :(得分:0)

Q1:如果你想从数字中恢复字符串,那么你可以使用:

1a:字符串的加密,除非先将字符串压缩,否则大小相同或更长。这将给出一组随机查找字节,可以显示为Base-64。

1b:数据库或地图,数字是地图/数据库中字符串的索引。

Q2:字符串不必是可恢复的。

这里有各种各样的想法。您可以以十六进制或Base-64显示散列以避免出现负号。 Base-64中唯一的非字母数字字符是'+','/'和'='。对于几乎唯一的哈希,您将需要一些加密大小,MD5(128位),SHA-1(160位)或SHA-2(256或512位)。

MD5哈希在十六进制中看起来像“d131dd02c5e6eec4693d9a0698aff95c”;散列越大,碰撞的可能性就越小。

Rossum的