11/20 09:38

比较器

﻿﻿

﻿

﻿﻿对应的比较器实现如下：

﻿﻿可知其采用的 Integer.compare 方法对两个整数进行比较操作，查看 Integer#compare 方法的源码：

/**
* Compares two {@code int} values numerically.
* The value returned is identical to what would be returned by:
* <pre>
*    Integer.valueOf(x).compareTo(Integer.valueOf(y))
* </pre>
*
* @param  x the first {@code int} to compare
* @param  y the second {@code int} to compare
* @return the value {@code 0} if {@code x == y};
*         a value less than {@code 0} if {@code x < y}; and
*         a value greater than {@code 0} if {@code x > y}
* @since 1.7
*/
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}

切量比例

﻿﻿以上代码是某段业务逻辑中初始切量比例实现，取余 100 的模式常用于按比例切量、按比例降级等业务场景。以上代码使用 userPin 的哈希值取余 100 判断是否小于切量比例以决定是否执行新业务逻辑，如果我们查看 java.lang.String#hashCode 的源码实现：

/**
* Returns a hash code for this string. The hash code for a
* {@code String} object is computed as
* <blockquote><pre>
* s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
* </pre></blockquote>
* using {@code int} arithmetic, where {@code s[i]} is the
* <i>i</i>th character of the string, {@code n} is the length of
* the string, and {@code ^} indicates exponentiation.
* (The hash value of the empty string is zero.)
*
* @return  a hash code value for this object.
*/
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;

for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}

﻿﻿以上修复方案看似不再存在问题，但是并不能保证完全正确，我们查看 Math.abs 的源码实现：

/**
* Returns the absolute value of an {@code int} value.
* If the argument is not negative, the argument is returned.
* If the argument is negative, the negation of the argument is returned.
*
* <p>Note that if the argument is equal to the value of
* {@link Integer#MIN_VALUE}, the most negative representable
* {@code int} value, the result is that same value, which is
* negative.
*
* @param   a   the argument whose absolute value is to be determined
* @return  the absolute value of the argument.
*/
public static int abs(int a) {
return (a < 0) ? -a : a;
}

x = Integer.MIN_VALUE:
10000000_00000000_00000000_00000000

~x:
01111111_11111111_11111111_11111111

(~x) + 1:
10000000_00000000_00000000_00000000

﻿

总结

• java.lang.String#hashCode 在计算过程中可能因为整数越界导致返回值为负数
• Java 语言中的 % 是取余而不是取模，如：(-21) % 4 = (-21) - (-21) / 4 *4 = -1
• Math.abs(int a) 当入参是 Integer.MIN_VALUE 时返回值依然是负数 Integer.MIN_VALUE

0 评论
0 收藏
0