浏览Guava的源代码时,遇到了以下代码(hashCode
内部类的实现的一部分CartesianSet
):
int adjust = size() - 1;
for (int i = 0; i < axes.size(); i++) {
adjust *= 31;
adjust = ~~adjust;
// in GWT, we have to deal with integer overflow carefully
}
int hash = 1;
for (Set<E> axis : axes) {
hash = 31 * hash + (size() / axis.size() * axis.hashCode());
hash = ~~hash;
}
hash += adjust;
return ~~hash;
两者的adjust
和hash
是int
秒。根据我对Java的了解,它~
意味着按位取反,因此adjust = ~~adjust
并且hash = ~~hash
应该使变量保持不变。运行小型测试(当然会启用断言),
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
assert i == ~~i;
}
确认这一点。假设番石榴人知道他们在做什么,那么他们一定有理由这样做。问题是什么?
编辑如评论中所指出,上面的测试不包括i
equals 的情况Integer.MAX_VALUE
。由于i <= Integer.MAX_VALUE
始终为真,因此我们需要在循环外检查该大小写,以防止其永远循环。但是,线
assert Integer.MAX_VALUE == ~~Integer.MAX_VALUE;
产生编译器警告“比较相同的表达式”,这几乎可以解决这个问题。
42
这些天来,@dr_andonuts Guava是一个非常标准的库,要包含在项目中-我认为建议不要太远。
—
yshavit 2015年
断言不检查边缘情况
—
Franky
Integer.MAX_VALUE
。与对比-(-Integer.MIN_VALUE) != Integer.MIN_VALUE
。
@ maaartinus,@ hvd,感谢您指出这一点。现在我记得了
—
Franky
-x = (~x) + 1
。
@dr_andonuts拖钓?为什么要逃避您不了解的事情。这就是StackOverflow的目的:帮助您学习。
—
Jared Burrows 2015年