String-hashcode疑问
今天闲来没事看String
的源码,在看到hashCode
方法里的实现,总感觉有点问题,以前就是看看了实现并没有太在意效率,下面就是String
的hashCode
方法代码。h = 31 * h + val[i]
要执行n次,时间复杂度为O(n)
。时间复杂度上我们不能减少,但是为什么不把h = 31 * h + val[i]
用位运算代替呢。比如:
int tmp = val[i] - h;
h <<= 5;
h += tmp;
本来以为可能是三行代码会导致代码的效率反而降低,但是通过测试后发现,位运算效率还是比较高些
下面是
jdk
中String
的hashCode
源码: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;
}
为了进行检验,编写下面的程序,初步估计等下面程序跑完,已经是我毕业了,所以放到服务器上去跑了,等我毕业再来重写这篇文章吧
import java.time.Duration;
import java.time.Instant;
import java.util.Random;
public class Main {
public static void main(String[] args) {
int one = 0;
int two = 0;
int balance = 0;
System.out.println("开始计算");
for (int i = 1;
i < Integer.MAX_VALUE;
i++) {
int c = new Random().nextInt(128);
int result = compareTest(i, (char) c);
if (result == 0)
balance++;
else if (result < 0)
one++;
else
two++;
}
System.out.printf("one耗时少的次数:%d\ntwo耗时少的次数:%d\nbalance平衡次数:%d", one, two, balance);
}private static int compareTest(int n, char c) {
Instant start01 = Instant.now();
int oneTime = testOne(n, c);
Instant end01 = Instant.now();
int nano01 = Duration.between(end01, start01).getNano();
Instant start02 = Instant.now();
int twoTime = testTwo(n, c);
Instant end02 = Instant.now();
int nano02 = Duration.between(end02, start02).getNano();
if (oneTime != twoTime) {
throw new RuntimeException("当前n=" + n + ",c=" + c + ",oneTime=" + oneTime + ",twoTime=" + twoTime);
}
return nano01 - nano02;
}private static int testOne(int n, char c) {
char[] val = {c};
int h = 0;
for (int i = 0;
i < n;
i++) {
h = h * 31 + val[0];
}
return h;
}private static int testTwo(int n, char c) {
char[] val = {c};
int h = 0;
for (int i = 0;
i < n;
i++) {
int tmp = val[0] - h;
h <<= 5;
h += tmp;
}
return h;
}
}
【String-hashcode疑问】如果有大神知道,还望指导一二。
推荐阅读
- 2019-02-13——今天谈梦想()
- Ⅴ爱阅读,亲子互动——打卡第178天
- 我错了,余生不再打扰
- 今天写一些什么
- 2019.4.18感恩日记
- “不完美,才美”01(190410)
- 离开美即
- 我没想好
- 8月10日安静
- 一个人值班