== vs equals vs XOR基准

时间:2015-06-10 14:36:38

标签: java string-comparison xor

我正在做基准测试,以便在比较对象时找出==equals^ (XOR)哪些可能更快。为此,我写了这个程序,得到了以下结果:

第一次迭代:

equals  took : 345
==  took : 625
xor  took : 284  

第二次迭代:

equals  took : 346
==  took : 182
xor  took : 254  

100次迭代后的总数:

average equals:  305
average ==:  164
average XOR:  246

我在这里有几个问题:

  1. 使用equals方法比第一次使用hashCode()更快,但在第二次迭代后使用哈希码变得更快。所以说是否可以安全 我随着时间的推移使用相同的数据集来进行一些计算 使用hashCode()而不是equals()
  2. 的速度更快
  3. 检查String.hashCode()实施后,我知道为什么hashCode()第二次变得更快,但为什么XOR变得更快?我无法看到任何逻辑。
  4. 这是仅供参考的程序:

    public static void main(String... args) throws Exception{
    
        String[] set1=new String[10000000];
        String[] set2=new String[10000000];
        Random r=new Random();
        for(int i=0;i<10000000;i++){
            int next=r.nextInt(1000);
            set1[i]=next+"";
            set2[i]=next+"";
        }
    
    
        for(int q=0;q<2;q++){  // change 2 to another number for more iterations
            long start0=System.currentTimeMillis();
            int equals0=0;
            for(int i=0;i<1;i++){
                for(int j=set2.length-1;j>=0;j--){
                    if(set1[i].equals(set2[j])){
                        equals0++;
                    }
                }
            }
            System.out.println("equals  took : " + (System.currentTimeMillis()-start0));
    
    
            long start1=System.currentTimeMillis();
            int equals1=0;
            for(int i=0;i<1;i++){
                for(int j=set2.length-1;j>=0;j--){
                    if(set1[i].hashCode()==set2[j].hashCode()){
                        equals1++;
                    }
                }
            }
            System.out.println("==  took : " + (System.currentTimeMillis()-start1));
    
    
    
            int equals2=0;
            long start2=System.currentTimeMillis();
            for(int i=0;i<1;i++){
                for(int j=set2.length-1;j>=0;j--){
                    if((set1[i].hashCode() ^ set2[j].hashCode())==0){
                        equals2++;
                    }
                }
            }
            System.out.println("xor  took : " + (System.currentTimeMillis()-start2));
    
        }
    

    编辑: 运行程序运行100次迭代后,我意识到只有最后一次迭代才会加速使用XOR。仍然,我不太确定最后一次迭代有什么特别之处?

2 个答案:

答案 0 :(得分:2)

由于比较对象的唯一方法是使用equals()这个问题没有实际意义,可能适用的唯一选择取决于具体情况和用例是身份比较(== )。

但是身份比较和平等不是同一个概念,所以你需要仔细决定哪一个是用例的正确工具。

答案 1 :(得分:1)

让我们有两个方法的look into the implementations

<强> hashCode()方法

在查看Hashcode函数的实现时,我们可以看到它依赖于String长度,这会影响计算哈希码所需的时间。这解释了为什么在你的情况下它有时更快。无论如何,这种方法不适合比较不同长度的非常长的字符串,因为它的值限制为32位。可能会发生两个不同(非常长)的字符串具有相同的值。 hashCode()方法也只进行纯数学计算哈希值。

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;
}

<强>等于()

在查看equals的实现时,我们也可以看到这个是长度依赖的。但是与hasCode()实现不同,此方法在字符串不相等时退出循环。这可以在某些情况下使比较更快。始终为整个String计算哈希码方法。 equals方法在while循环中有一个if语句,这使得计算比hashCode()循环慢。

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = count;
            if (n == anotherString.count) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = offset;
                int j = anotherString.offset;
                while (n-- != 0) {
                    if (v1[i++] != v2[j++])
                        return false;
                }
                return true;
            }
        }
        return false;
    }

<强> XOR

唯一解释为什么XOR部分比==部分慢,逻辑表达式不同。 ==表达式为A == B,其中XOR为(A XOR B) == 0。但我不完全确定这个,因为时间差异几乎是50%。 最后你XOR比较是没用的,因为它也会调用像你==实现那样的hashCode()方法,其中花费的时间最多。

你应该坚持使用equals方法,这是唯一可靠的方法。