获取String的int表示

时间:2008-09-05 16:11:44

标签: java performance string

我正在寻找一种方法来创建任意字母数字String的int \ long表示。哈希代码不会这样做,因为我无法承受哈希冲突,即表示必须是唯一且可重复的。

数字表示将用于执行有效(希望)比较。数字键的创建需要一些时间,但它只需要发生一次,而我需要对它进行大量的比较 - 希望比比较原始字符串要快得多。

关于更快的字符串比较的任何其他想法也将非常受欢迎...

14 个答案:

答案 0 :(得分:12)

除非你的字符串长度有限,否则你无法避免碰撞。

整数(2 ^ 32)有4294967296个可能的值。如果您的字符串包含4个以上的ASCII字符或两个以上的unicode字符,则可能的字符串值可能超过可能的整数值。每个可能的5个字符串都不能有唯一的整数值。长值具有更多可能的值,但它们仅为每个可能的8个ASCII字符串提供唯一值。

哈希代码作为两个步骤很有用:首先查看哈希代码是否匹配,然后检查整个字符串。对于大多数不匹配的字符串,您只需要执行第一步,而且速度非常快。

答案 1 :(得分:10)

难道你不能只用哈希码开始,如果哈希码匹配,那就做一个逐字符比较吗?

答案 2 :(得分:5)

琴弦有多长?如果它们非常短,那么可以通过将字符视为基数36(26 + 10)中的数字来生成唯一ID,这些数字形成 n -digits数字,其中 n 是字符串的长度。另一方面,如果字符串足够短以允许这样做,那么直接比较也不会成为问题。

否则,您将不得不生成无冲突的哈希,这只能在事先知道完整的问题空间时才能完成(即,如果您知道可能发生的所有字符串)。您将需要查看perfect hashing,尽管找到一个我知道的完美哈希函数的唯一可行算法是概率性的,因此在理论上冲突仍然是可能的。

可能还有其他方法可以找到这样的功能。 Knuth称这在TAoCP中是一个“相当有趣......难题”,但他也没有给出算法。

通常,您提供的信息太少,无法找到不需要以某种方式探测整个问题空间的算法。这确实意味着问题具有指数运行时间,但可以使用机器学习启发式解决。我不确定你的情况是否合适。

答案 3 :(得分:2)

也许:

String y = "oiu291981u39u192u3198u389u28u389u";
BigInteger bi = new BigInteger(y, 36);
System.out.println(bi);

答案 4 :(得分:2)

在一天结束时,单个字母数字字符至少有36个可能的值。如果你包括标点符号,小写字母等,那么你可以很容易地传递72个可能的值。

允许您快速比较字符串的非碰撞数字必然会随着字符串的长度呈指数级增长。

因此,首先必须决定您希望比较的最长字符串。假设它的长度为N个字符,假设您只需要大写字母和数字0-9那么您需要有一个可以高达的整数表示 36 ^ N

对于长度为25的字符串(通用名称字段),您最终需要一个130位的二进制数。

如果你把它组成32位数,你需要4.然后你可以比较每个数字(四个整数比较应该没有时间,与走绳子相比)。我会推荐一个大数字库,但对于这个专业案例,我很确定你可以编写自己的并获得更好的性能。

如果你想处理每个字符72个可能的值(大写,小写,数字,标点......),你需要10个字符,那么你需要62位 - 两个32位整数(如果你需要一个64位) '依赖于支持64位计算的系统)

但是,如果您无法限制字符串中的数字(即,可能是256个字母/数字/字符/等中的任何一个),并且您无法定义字符串的大小,那么比较字符串直接是唯一的方法,但有一条捷径。

将字符串的指针强制转换为32位无符号整数数组,并一次比较字符串4个字节(或64位处理器上一次64位/ 8字节)。这意味着100个字符的字符串只需要25个比较最大值才能找到更大的值。

您可能需要重新定义字符集(并转换字符串),以便优先级较高的字符分配的值接近0,较低的优先级值接近255(反之亦然,具体取决于您的方式)比较它们。)

祝你好运!

- 亚当

答案 5 :(得分:1)

一开始就有几个问题:

  1. 您是否测试过简单的字符串比较太慢了?
  2. 比较结果如何('ABC'=='abc'或'ABC'!='abc')?
  3. 您需要比较多少个字符串?
  4. 你需要做多少比较?
  5. 你的字符串是怎样的(长度,字母大小写)?
  6. 据我所知,Java中的String是一个对象,两个相同的字符串指向同一个对象。

    所以,也许它足以比较对象(可能已经以这种方式实现了字符串比较)。

    如果它没有用,你可以尝试在第一个元素长度时使用字符串对象的Pascal实现,如果你的字符串有不同的长度,这应该节省一些CPU时间。

答案 6 :(得分:1)

只要它是一个哈希函数,无论是String.hashCode(),MD5还是SHA1,除非你对字符串的长度有一个固定的限制,否则冲突是不可避免的。从数学上看,从无限群到有限群的一对一映射是不可能的。

退后一步,是否必须避免碰撞?

答案 7 :(得分:0)

你的琴弦有多长?除非您选择比字符串长的int表示,否则无论您使用什么转换,都可能发生冲突。因此,如果您使用32位整数,则只能唯一地表示最多4个字节的字符串。

答案 8 :(得分:0)

你的琴弦有多大?任意长的字符串不能压缩成32/64位格式。

答案 9 :(得分:0)

如果你不想碰撞,可以试试像SHA-512这样疯狂的事情。我无法保证不会发生碰撞,但我认为他们还没有找到任何碰撞。

答案 10 :(得分:0)

假设“字母数字”表示字母和数字,您可以将每个字母/数字视为基数为36的数字。不幸的是,大字符串会导致数字迅速增长,你不得不求助于大整数,这几乎没有效率。

如果您进行比较(即搜索特定字符串)时字符串通常不同,则哈希可能是您的最佳选择。一旦获得潜在的命中,您可以进行字符串比较以确定。精心设计的哈希会使碰撞极为罕见。

答案 11 :(得分:0)

似乎MD5哈希值可以正常工作。哈希冲突的风险极不可能。根据字符串的长度,生成int / long的哈希会很快遇到最大值问题。

答案 12 :(得分:0)

你为什么不做1stChar +(10 x 2ndChar)+ 100 x(3rdChar)....之类的东西,你使用每个字符的简单整数值,即a = 1,b = 2等,或者只是整数值,如果它不是一个字母。这将为每个字符串提供唯一值,即使是2个字符串,它们只是不同顺序的相同字母。

当然如果你需要担心Unicode而不仅仅是ASCII而变得更复杂,如果你需要使用长字符串,数字可能会变大。

标准的Java字符串比较函数是否绝对不够高效?

答案 13 :(得分:0)

  

字符串长度可能会有所不同,但现在让我们说10个字符。

在这种情况下,为了保证唯一性,您必须使用某种大整数表示。我怀疑对大整数进行比较会比首先进行字符串比较快得多。我将在这里说出其他人所说的内容,使用某种哈希值,然后在哈希匹配的情况下检查原始字符串以清除任何冲突。

在任何情况下,如果你的字符串大约是10个字符,我怀疑比较一堆32位哈希将比直接字符串比较快得多。我想你必须问自己,这是否真的值得额外的复杂性。