Stringbuilder与String的对象,在HashMap的get方法差异.
引言:之前需要使用对象来跨越不同方法进行传递,结果返回后再map方法中始终无法获得到...
经过源码分析,是由于hash()方法导致的,使用StringBuilder对象即使值与String一致,产生的索引
也是不同的;
public class Test{
public static void main(String[] args) {
StringBuilder name=new StringBuilder();
name.append("key");
Map<String, Object> tempMap = new HashMap<String, Object>();
tempMap.put("key","value");
//StringBulider对象的"key"并未获取到值
System.out.println(tempMap.get(name));//输出:null
System.out.println(tempMap.get("key"));//输出:value
//查看源码分析原因,是由hash方法导致的索引值指向不同位置,使得返回结果不一致;
System.out.println(hash(name));//输出:1883673307
//只需要将StringBuilder对象转换为String即可正确获取;
System.out.println(hash(String.valueOf(name)));//输出:99486
System.out.println(hash("key"));//输出:99486
}
/**
*hash方法,源码不是static方法,此处加上方便测试
**/
static final int hash(Object k) {
//源码中声明:transient int hashSeed = 0; 其初始值=0;且put方法未涉及此字段,所以还是0;
int h = 0; //int h = hashSeed;
if (0 != h && k instanceof String) {
return sun.misc.Hashing.stringHash32((String) k);
}
h ^= k.hashCode();
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
}
//-----------------------------------------源码分析:查看HashMap的get方法----------------------------------------------
public V get(Object key) {
if (key == null)
return getForNullKey();
Entry<K,V> entry = getEntry(key); //获取值的方法
return null == entry ? null : entry.getValue();
}
final Entry<K,V> getEntry(Object key) {
if (size == 0) {
return null;
}
int hash = (key == null) ? 0 : hash(key);//底层是table,索引值导致返回结果的不一致
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
}
return null;
}
final int hash(Object k) {
int h = hashSeed;
if (0 != h && k instanceof String) {
return sun.misc.Hashing.stringHash32((String) k);
}
h ^= k.hashCode();
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
static int indexFor(int h, int length) {
// assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";
return h & (length-1);
}