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

如何在Java中生成共享相同哈希代码的字符串?,java,string,hashcode,Java,String,Hashcode,用Java编写的现有系统使用字符串的哈希代码作为负载平衡的路由策略 现在,我不能修改系统,但需要生成共享相同哈希代码的字符串来测试最坏的情况 我从命令行提供这些字符串,并希望系统将所有这些字符串路由到同一个目的地 是否可以生成大量共享相同哈希代码的字符串 为了澄清这个问题: String[] getStringsInSameHashCode(int number){ //return an array in length "number" //Every element of t

用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 s=“一些字符串”
String s = "Some String"
for (int i = 0; i < SOME_VERY_BIG_NUMBER; ++i) {
    String copy = new String(s);

    // Do something with copy.
}
for(int i=0;i

这对你有用吗?它只是创建了许多相同字符串文本的副本,您可以在测试中使用这些副本。

您可以插入java.lang.String类,使其方法hashCode()始终返回相同的数字

我认为Javassist是实现这种检测的最简单的方法

简言之:

  • 使用java代理获取java.lang.Instrumentation.Instrumentation的实例(有关详细信息,请参阅)
  • 使用Instrumentation.redefineClasses(ClassDefinition[])方法重新定义java.lang.String类
代码大致如下所示:


另外,不要忘记代理清单文件必须指定
可以重定义类:true
,以便能够使用重定义类(ClassDefinition[])方法。

基本上,只要您匹配, a1*31+b1=a2*31+b2,表示(a1-a2)*31=b2-b1

你会得到

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 void testN()引发异常{
列表l=HashCUtil.generateN(3);
对于(int i=0;i
下面是源代码,可能效率不高,但可以正常工作:

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;      
    }
}
公共类HashCUtil{
私有静态字符串[]基=新字符串[]{“Aa”,“BB”};
公共静态列表生成器(int n)
{

如果(n我认为从长字符串中查找相等的哈希字符串太难,那么在查找短字符串(2或3)的相等哈希字符串时很容易。 看下面的等式。(对不起,我不能发布图片,因为我是新会员)

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

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

下面的代码在小级别下运行良好,如果级别较大,则会出错,使字符值溢出,如果需要,我将稍后修复(此代码更改2个第一字符,但我将编辑代码到2个最后字符,因为2个第一字符是具有最大值的计算)

公共静态字符串samehash(字符串s,int级别){
如果(s.长度()<2)
返回s;
String sub2=s.substring(0,2);
char c0=sub2.字符(0);
字符c1=子2.字符(1);
c0=(字符)(c0+电平);
c1=(字符)(c1-31*级);
String newsub2=新字符串(新字符[]{c0,c1});
字符串re=newsub2+s.substring(2);
返回re;
}

我想知道是否有“通用”解决方案;例如,某个常量字符串
XYZ
,例如

    s.hashCode() == (s + XYZ).hashCode() 
对于任何字符串,
s
。找到这样一个字符串需要解一个相当复杂的方程……这超出了我生疏的数学能力。但后来我意识到,
h==31*h+ch
总是
真的
,而
h
ch
都是零

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

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

如果NUL字符对您来说是有问题的,那么在哈希代码为零的任何字符串前加前缀也会起作用……尽管冲突字符串会比使用零的字符串长。

给定字符串X,那么字符串Y=“\u0096\0\0ɪ\0ˬ”+X将与X共享相同的哈希代码

说明:

  • String.hashcode()返回整数,java中的每个整数X都有一个属性X=X+2*(Integer.MAX\u VALUE+1)

  • 所以我们只需要找到字符串M,它的属性是M的hashcode%(2*(Integer.MAX_VALUE+1))=0

  • 我发现“\u0096\0\0ɪ\0ˬ”:\u0096的ascii码是150,\0的ascii码是0,ɪ的ascii码是618,ˬ的ascii码是748,所以它的哈希码是150*31^5+618*31^2+748=2^32=0


  • 取决于您想要哪个字符串,我选择这个。

    使用equals字符串不是一个选项?看看字符串源代码。它们需要具有不同值的字符串还是只是不同的字符串对象?我知道java如何为字符串生成哈希代码,但不知道如何使用相同的哈希代码生成不同的字符串文字e、 我不能重写字符串的任何方法。@Code GuruSorry我没有说得足够清楚。相同的字符串被点亮
       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;
        }
    
        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;
    }
    
        s.hashCode() == (s + XYZ).hashCode() 
    
        public String collider(String s) { 
            return "\0" + s;
        }