HashMap的文章有很多
可以先读读相关文章,及原理篇。本篇主要是从实践探索里面的变化,再对比看原理就会更加清晰.
此话题虽然老生常谈:然而理论完了实践一把
其中不少收获,Android中的和Java的设计还是有所不同。
Android给的英文注释也是16,实践一把发现注释欺骗了你。
实践是检验真理的唯一标准。于是还是实践一把,验证一下,扩容因子,以及扩容演化,运算的过程步骤。
Android初始化数组不是16 各版本不一样
之前的是4,后来变成0,第一次put才给4.Android对内存的使用考虑是慎之又慎。
而且里面用到很多巧妙的位运算
和数据结构,算法设计。故而HashMap的探讨真是前赴后继,乐此不疲。
周末提起,又探究一翻,主要利用反射打印其变化过程。明白了其中不少道理,受益匪浅,其中一些位运算算法还未理解其精髓。这个若详细探究起来几天几夜也未必,做了个简易探索。有兴趣的可以一观, 不足之处,还望指正
HashMap 有局限不能查询区间问题。
Java8又用到红黑树。
前天翻书数据结构,说二叉树深度过大时出现了B树B+树。用于数据库之中,使用少量内存查询更高效查询对象。
相关文章
HashMap实现原理及源码分析
http://www.cnblogs.com/chengxiao/p/6059914.html
Java8系列之重新认识HashMap
https://zhuanlan.zhihu.com/p/21673805
HashMap的工作原理 提问篇
http://www.importnew.com/7099.html
深入Java集合学习系列:HashMap的实现原理
http://zhangshixi.iteye.com/blog/672697
HashMap实现原理分析(详解)
http://www.cnblogs.com/xingzc/p/5765572.html
从零 == 号开始吧
来来看例子
public static void main(String[] args) {
String ss = "a";
int hashCode = ss.hashCode();
String s2 = "a";
int hashCode2 = s2.hashCode();
System.out.println(hashCode);
System.out.println(hashCode2);
System.out.println(ss == s2);
System.out.println(ss.equals(s2));
}
运行结果
97
97
true
true
看例子
public static void main(String[] args) {
String ss = "a";
int hashCode = ss.hashCode();
System.out.println(hashCode);
String s2 = new String("a");
System.out.println(s2.hashCode());
System.out.println(ss == s2);
System.out.println(ss.equals(s2));
}
运行结果
97
97
false
true
对比
public static void main(String[] args) {
String ss = new String("a");
int hashCode = ss.hashCode();
System.out.println(hashCode);
String s2 = new String("a");
System.out.println(s2.hashCode());
System.out.println(ss == s2);
System.out.println(ss.equals(s2));
}
运行结果
97
97
false
true
放在Set集合里面
public static void main(String[] args) {
String ss = "a";
String s2 = "a";
String s3 = new String("a");
String s4 = new String("a");
Set set = new HashSet();
// Set set = new TreeSet();
set.add(ss);
set.add(s2);
set.add(s3);
set.add(s4);
for (Object object : set) {
System.out.println("set.size()===" + set.size() + " ; object=="+ object);
}
}
运行结果
set.size()===1 ; object==a
在Set里面认为对象相等。
HashSet实现是利用了HashMap去进行的比较 看Add方法 ; 利用了静态全局变量 Value为相同的值 如果Key相同那么map中只有一个对象 ; 我们再看HashMap的put方法。
private transient HashMap<E,Object> map;
private static final Object PRESENT = new Object();
public HashSet() {
map = new HashMap<>();
}
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
HashMap上场 , HashMap有多个版本,Android中的不同版本JDK24和JDK25不同
初始化容量也不同 不是我们看到的Java的16.
Java7和Java8的也不同 Java8用到红黑树等 默认的扩容因子还都是0.75
版本对比先不比较,比较了一个晚上都凌乱了。
HashMap put方法源码
先看AndroidSDK 25版本中的HashMap源码
自己点进去看一下。我们利用反射先看看初始化的属性
HashMap 网上原理一大堆没看一次,大有受益又有疑问,
实践是检验真理的唯一标准,我们来实践一下。
我们采用实践通过实践看原理
先建一个空的HashMap 反射一下
HashMap hashMap = new HashMap();
ReflectUtils.getFildValue(hashMap);
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class ReflectUtils {
public static void getFildValue(Object object) {
Field[] fields = object.getClass().getDeclaredFields();
System.out.println("----------------------start----------------------------------------------------------------------------");
System.out.println("class :" + object.getClass());
for(Field f : fields){
f.setAccessible(true);
int mod = f.getModifiers();
Object o = null;
try {
o = f.get(object);
System.out.println( Modifier.toString(mod) + " " + f.getType().getName() + " " + f.getName() + " == " + o);
if (o != null) {
Class<?> type = o.getClass();
if (type.isArray()) {
System.out.println("是数组:"+type.isArray());
Class<?> elementType = type.getComponentType();
System.out.println("Array of: " + elementType);
System.out.println("Array length: " + Array.getLength(o));
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
System.out.println("------------------------");
}
System.out.println("----------------------end-------------------------------------------------------------------------");
}
}
然后我们看到各种的初始化的值 对于static final的不会改变 以后就不再打印
I/System.out: transient [Ljava.util.HashMap HashMapEntry;table==[Ljava.util.HashMap HashMapEntry;@6ca7431
这个是数组。
不会变化的 记住就行
static final int DEFAULT_INITIAL_CAPACITY = 4; //默认初始化容量
static final int MAXIMUM_CAPACITY = 1 << 30; // 最大容量
static final float DEFAULT_LOAD_FACTOR = 0.75f; //默认扩容因子