当前位置: 首页 > 知识库问答 >
问题:

如何在Java中生成共享相同哈希代码的字符串?

秋向阳
2023-03-14

用Java编写的现有系统使用字符串的哈希代码作为负载平衡的路由策略。

现在,我无法修改系统,但需要生成共享相同哈希代码的字符串来测试最坏的情况。

我从命令行提供这些字符串,并希望系统将所有这些字符串路由到同一个目的地。

有可能生成大量共享相同哈希代码的字符串吗?

为了明确这个问题:

String[] getStringsInSameHashCode(int number){
    //return an array in length "number"
    //Every element of the array share the same hashcode. 
    //The element should be different from each other
}

备注:任何hashCode值均可接受。对字符串是什么没有限制。但它们应该彼此不同。

编辑:不接受String类的重写方法,因为我从命令行提供这些字符串。

仪表也是不可接受的,因为这会对系统产生一些影响。

共有3个答案

梁池暝
2023-03-14

我想知道是否有一个“通用”的解决方案;e、 g.一些常量字符串XYZ,这样

    s.hashCode() == (s + XYZ).hashCode() 

对于任何字符串s。找到这样一根弦需要解一个相当复杂的方程。。。这超出了我生疏的数学能力。但后来我明白了,当hch都为零时,h==31*h ch总是true

基于这一认识,以下方法应使用与参数相同的哈希代码创建不同的字符串:

    public String collider(String s) { 
        return "\0" + s;
    }

如果NUL字符对您来说是有问题的,那么在哈希代码为零的任何字符串前加前缀也可以。。。尽管碰撞的字符串比使用零的字符串要长。

夹谷山
2023-03-14

我认为从一个长字符串中找到一个相等的哈希字符串太难了,当找到一个短字符串(2或3)的相等哈希字符串时很容易。看看下面的等式。(抱歉,我不能发布图片,因为我是新会员)

请注意,“FB”和“Ea”具有相同的哈希代码,任何两个字符串,如s1“FB”s2和s1“Ea”s2,都将具有相同的哈希代码。因此,简单的解决方案是找到现有字符串的任何2字符子字符串,并替换为具有相同哈希代码的2字符子字符串

例如,我们有字符串“helloworld”获取2-char子字符串“he”,hashcode(“he”)='h'*31'e'=('h'*31 31)('e'-31)=('h'1)*31'F'='i''F'=hashcode(“iF”)所以愿望字符串是“iFlloworld”,我们将“h”增加了1,我们可以增加2或3等(但如果它溢出char值将是错误的)

下面的代码在小级别运行良好,如果级别大就会出错,使char值溢出,如果你愿意,我稍后会修复它(此代码更改2个第一个字符,但我会将代码编辑为2个最后一个字符,因为2个第一个字符是最大值的计算)

    public static String samehash(String s, int level) {
    if (s.length() < 2)
        return s;
    String sub2 = s.substring(0, 2);
    char c0 = sub2.charAt(0);
    char c1 = sub2.charAt(1);
    c0 = (char) (c0 + level);
    c1 = (char) (c1 - 31 * level);
    String newsub2 = new String(new char[] { c0, c1 });
    String re =  newsub2 + s.substring(2);
    return re;
}
谭嘉容
2023-03-14

看一个测试方法,基本上,只要你匹配,a1*31 b1=a2*31 b2,这意味着(a1-a2)*31=b2-b1

public void testHash()
{
    System.out.println("A:" + ((int)'A'));
    System.out.println("B:" + ((int)'B'));
    System.out.println("a:" + ((int)'a'));

    System.out.println(hash("Aa".hashCode()));
    System.out.println(hash("BB".hashCode()));
    System.out.println(hash("Aa".hashCode()));
    System.out.println(hash("BB".hashCode()));


    System.out.println(hash("AaAa".hashCode()));
    System.out.println(hash("BBBB".hashCode()));
    System.out.println(hash("AaBB".hashCode()));
    System.out.println(hash("BBAa".hashCode()));

}

你会得到

A:65
B:66
a:97
2260
2260
2260
2260
2019172
2019172
2019172
2019172

编辑:有人说这不够简单。我在下面添加了一部分

    @Test
    public void testN() throws Exception {
        List<String> l = HashCUtil.generateN(3);
        for(int i = 0; i < l.size(); ++i){
            System.out.println(l.get(i) + "---" + l.get(i).hashCode());
        }
    }
AaAaAa---1952508096
AaAaBB---1952508096
AaBBAa---1952508096
AaBBBB---1952508096
BBAaAa---1952508096
BBAaBB---1952508096
BBBBAa---1952508096
BBBBBB---1952508096

下面是源代码,它可能效率不高,但它可以工作:

public class HashCUtil {

    private static String[] base = new String[] {"Aa", "BB"};

    public static List<String> generateN(int n)
    {
        if(n <= 0)
        {
            return null;
        }

        List<String> list = generateOne(null);
        for(int i = 1; i < n; ++i)
        {
            list = generateOne(list);
        }

        return list;
    }


    public static List<String> generateOne(List<String> strList)
    {   
        if((null == strList) || (0 == strList.size()))
        {
            strList = new ArrayList<String>();
            for(int i = 0; i < base.length; ++i)
            {
                strList.add(base[i]);
            }

            return strList;
        }

        List<String> result = new ArrayList<String>();

        for(int i = 0; i < base.length; ++i)
        {
            for(String str: strList)
            {   
                result.add(base[i]  + str);
            }
        }

        return result;      
    }
}

查看String.hash代码()

   public int hashCode() {
    int h = hash;
    if (h == 0) {
        int off = offset;
        char val[] = value;
        int len = count;

            for (int i = 0; i < len; i++) {
                h = 31*h + val[off++];
            }
            hash = h;
        }
        return h;
    }
 类似资料:
  • 问题内容: 用Java编写的现有系统将字符串的哈希码用作其负载平衡的路由策略。 现在,我 无法修改系统, 但需要生成共享相同哈希码的字符串以测试最坏的情况。 我从命令行提供了这些字符串,并希望系统将所有这些字符串路由到同一目的地。 是否可以生成大量共享相同哈希码的字符串? 为了使这个问题更清楚: 备注:任何hashCode值都是可接受的。字符串是什么没有限制。但是它们应该彼此不同。 编辑:Stri

  • 问题内容: 我有一个函数可以在C#中生成MD5哈希,如下所示: 在Java中,我的函数如下所示: C#代码生成:“ 02945C9171FBFEF0296D22B0607D522D”时,Java代码生成:“ 5a700e63fa29a8eae77ebe0443d59239”。 有没有办法为相同的字节数组生成相同的md5哈希? 一经请求: 这是java中的测试代码: 这是我在C#中的代码 干杯 问题

  • 问题内容: 我有一个Java应用程序,我想在其中生成字符串的id(以便将这些字符串存储在neo4j中)。为了避免数据重复,我想为存储在整数中的每个字符串生成一个ID,该ID对于每个字符串都应该是唯一的。我怎样才能做到这一点 ? 问题答案: 有64位。长度为9的A 有72位。从鸽子洞的原理 -您不能得到9个字符长的字符串到的唯一哈希。 如果你仍然想一个哈希:你可以只取两个标准的哈希函数[不同!] ,

  • 问题内容: 例如: 有任何内置功能可以做到这一点吗? 谢谢。 问题答案: 该散包是这很有帮助。请注意,这是对特定哈希实现的抽象。在软件包子目录中可以找到一些现成的。 例: (也在这里) 输出:

  • 最近,我参加了一次面试,遇到了一个关于哈希碰撞的很好的问题。 问题:给出一个字符串列表,把字谜一起打印出来。 示例: I/P: 、 、 、 、 、 、 、 、 、 、 、 、 {行为,上帝,动物,狗,猫} O/P:               演戏,猫,狗,上帝 我要创建hashmap并将单词作为键,将值作为字母表列表 为了避免冲突,我想为字母表生成唯一的哈希代码,而不是排序并使用排序后的单词作为

  • 问题内容: 我需要将字符串转换为某种形式的哈希。这在JavaScript中可行吗? 我没有使用服务器端语言,所以我不能那样做。 问题答案: Object.defineProperty(String.prototype, ‘hashCode’, { value: function() { var hash = 0, i, chr; for (i = 0; i < this.length; i++)