我正在做基准测试,以便在比较对象时找出==
,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
我在这里有几个问题:
equals
方法比第一次使用hashCode()更快,但在第二次迭代后使用哈希码变得更快。所以说是否可以安全
我随着时间的推移使用相同的数据集来进行一些计算
使用hashCode()
而不是equals()
?String.hashCode()
实施后,我知道为什么hashCode()
第二次变得更快,但为什么XOR
变得更快?我无法看到任何逻辑。这是仅供参考的程序:
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。仍然,我不太确定最后一次迭代有什么特别之处?
答案 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方法,这是唯一可靠的方法。