将非数字字符串转换为整数?

6

如何将非数字字符串转换为整数?

例如,我有:

String unique = "FUBAR";

有什么好的方法可以将该字符串表示为整数并且没有冲突,例如,“FUBAR”应始终表示为相同的数字,并且不应与任何其他字符串发生冲突。例如,String a =“A”; 应表示为整数1,但是有什么方法可以实现这一点(最好适用于所有Unicode字符串,但在我的情况下ASCII值可能足够)。


1
这就是字符编码的作用。将字符串转换为字节,你就得到了一个数字。 - tom
1
这里的目标是什么?有许多方法可以将字符串转换为数字并保持唯一性。毕竟,任何数据都被存储为一系列位,因此它更像是一种重新解释而不是转换。但如果你希望任何长度的字符串的结果适合单个Java int值,那么你需要一个哈希函数,其中有很多。然而,永远不可能有一个完美的哈希函数保证没有冲突,因为可能的字符串比ints还要多(鸽笼原理)。 - Mark Reed
1
我无法想到一种适用于所有 Unicode字符串的方法,无论它们有多长,都可以将它们转换为单个int。但是如果你找到了可靠的方法,请回来报价:数据压缩公司会爱上你的;-) - Sergey Kalinichenko
2
你是否在寻找https://dev59.com/WnE85IYBdhLWcg3wwWat? - LeeNeverGup
1
你所说的“integer”,是指Java中的int还是指“任意长度的整数”? - Bohemian
显示剩余2条评论
6个回答

9
这是不可能的。想一想,一个`Integer`只能有32位。所以,根据鸽巢原理,无论你使用什么转换技术,都必须存在至少两个具有相同`Integer`值的字符串。事实上,有无限多个相同的值...
如果你只是想要一个高效的映射,那我建议你直接使用由`hashCode()`返回的`int`,它实际上只有31位。

5
因为可以,所以被踩。十六进制数字包含字符,它们可以轻松地转换为十进制,而不会发生任何冲突。 - Torben
3
@909Niklas 什么?int idValue = (this.getClass().getName() + id).hashCode() - Mark Reed
1
@Torben,问题指定“无碰撞”。这是不可能的。 - Mark Reed
2
@Torben,没有任何可能保证不发生冲突。如果你找到了方法,请告诉我(而不是其他人)。 - Steve P.
2
顺便提一下,Object.hashCode() 是 31 位的。 - Peter Lawrey
显示剩余9条评论

3

你可以使用表格将字符串映射到唯一的 ID。通常情况下,没有一种通用的方法可以实现这一点。

final Map<String, Integer> map = new HashMap<>();
public int idFor(String s) {
    Integer id = map.get(s);
    if (id == null)
       map.put(s, id = map.size());
    return id;
}

注意:拥有唯一的id在哈希集合中并不能保证不发生冲突。
参考链接:http://vanillajava.blogspot.co.uk/2013/10/unique-hashcodes-is-not-enough-to-avoid.html

2
如果您知道字符串中使用的字符集,那么您可以将该字符串视为使用非十进制基数的数字。例如,十六进制数字包含从A到F的字母。
因此,如果您知道您的字符串仅包含来自8位字符集的字母,您可以将该字符串视为256进制数。伪代码如下:
number n;
for each letter in string
    n = 256 * n + (letter's position in character set)

如果您的字符集包含65535个字符,则在每一步上只需将“n”乘以该数字即可。但请注意,整数的32位很容易溢出。您可能需要使用能够容纳更大数字的类型。

1
private BigDecimal createBigDecimalFromString(String data)
{
    BigDecimal value = BigDecimal.ZERO;

    try
    {
        byte[] tmp = data.getBytes("UTF-8");
        int numBytes = tmp.length;
        for(int i = numBytes - 1; i >= 0; i--)
        {
            BigDecimal exponent = new BigDecimal(256).pow(i);
            value = value.add(exponent.multiply(new BigDecimal(tmp[i])));
        }
    }
    catch (UnsupportedEncodingException e)
    {
    }
    return value;
}

1
也许有点晚了,但我想简化一下(内部类似于@Romain Hippeau建议的BigDecimal)
public static BigInteger getNumberId(final String value) {
    return new BigInteger(value.getBytes(Charset.availableCharsets().get("UTF-8")));
}

1

无论接受何种答案,都可以通过计算字符串的哥德尔数将任何字符串表示为整数,该数是每个可能的字符串的质数唯一乘积。话虽如此,实现起来相当不切实际和缓慢,对于大多数字符串而言,您需要使用BigInteger而不是普通的整数,并且要将哥德尔数解码为相应的字符串,您需要拥有定义好的字符集。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接