Просматривая исходный код 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являются ints. Из того, что я знаю о Java, ~подразумевается побитовое отрицание, поэтому adjust = ~~adjustи hash = ~~hashследует оставить переменные без изменений. Запуск небольшого теста (с включенными утверждениями, конечно),
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
assert i == ~~i;
}
подтверждает это. Предполагая, что парни из гуавы знают, что они делают, у них должна быть причина для этого. Вопрос в чем?
РЕДАКТИРОВАТЬ Как указано в комментариях, тест выше не включает в себя случай, когда iравно Integer.MAX_VALUE. Так i <= Integer.MAX_VALUEкак всегда верно, нам нужно будет проверить этот случай вне цикла, чтобы предотвратить его зацикливание навсегда. Тем не менее, линия
assert Integer.MAX_VALUE == ~~Integer.MAX_VALUE;
выдает предупреждение компилятора «Сравнение идентичных выражений», которое в значительной степени его прибивает.
Integer.MAX_VALUE. Контраст с -(-Integer.MIN_VALUE) != Integer.MIN_VALUE.
-Integer.MIN_VALUEоборачивается Integer.MIN_VALUE, так отрицая, что снова просто производит Integer.MIN_VALUEснова.
-x = (~x) + 1.