没有特别说明线程安全,代表线程不安全
相等的对象必须具有相等的hashCode java.util.Collection接口, Map接口没有继承java.util.Collection接口容器容量大小*负载因子,就要resizekey.equals(k)去查找对应的entry:若为树则在树中通过key.equals(k)查找O(logn); 若为链表则在链表中通过key.equals(k)查找O(n) 容器容量大小*负载因子就要扩容原索引+2的n次方 扩容的时候需要重新计算Hash吗? 1.8之前需要,1.8中不需要. 在1.8中元素的位置要么是在原位置,要么是在原位置再移动2次幂的位置
HashMap有一个问题,就是迭代HashMap的顺序并不是HashMap元素插入的顺序,也就是无序,而LinkedHashMap是有序的。
accessOrder=true来达到按访问顺序排序的效果,也就是访问一个元素之后,会将它放到尾部accessOrder=true来达到按访问顺序遍历LinkedHashMap的效果。什么叫访问顺序?即通过get方法访问的元素,会放到链表尾部,也就是按照了访问时间进行排序,基于这个特性和LinkedHashMap虽然可以根据插入顺序和访问顺序排序,但是无法自定义排序规则,而TreeMap可以
key#compareTo方法进行比较,此种情况key必须实现Comparable接口;或者根据创建映射时提供的Comparator进行排序synchronized实现,效率低CAS+synchronized实现(锁粒度更细), 相对HashTable来说,性能好很多java.util.Collection接口, Map接口没有继承java.util.Collection接口System.arraycopy,效率很低,所以最好在初始化的时候指定大小增删操作都相对低效, 而改查操作比较高效arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
src:源数组;
srcPos:源数组要复制的起始位置;
dest:目的数组;
destPos:目的数组放置的起始位置;
length:复制的长度;
src 和 dest 必须是同类型或者可以进行转换类型的数组ReentrantLock获取锁,然后基于原数组复制出一个新的数组,在新数组的基础上修改java.util.Collection接口, Map接口没有继承java.util.Collection接口private static final Object PRESENT = new Object() map.keySet().iterator(). 也就是说HashSet依赖于HashMap实现,仅仅是利用了HashMap的key,value只是一个常量对象,没有什么意义 LinkedHashSet底层使用LinkedHashMap来保存所有元素,它继承自HashSet,其所有的方法操作上又与HashSet相同CopyOnWriteArrayList引用,也就是说它的实现完全基于CopyOnWriteArrayList ConcurrentModificationException Iterator时通过expectedModCount记录了当前的修改次数,在迭代时判断expectedModCount是否与modCount相等,不相等则抛出ConcurrentModificationException ThreadLocal中有一个内部类:ThreadLocalMap. 数据会被封装成Entry然后存到ThreadLocalMap中Thread中有一个ThreadLocalMap类型的属性:threadLocals threadLocals属性值为null,则创建一个ThreadLocalMap对象并赋值给当前线程的threadLocals属性,然后以ThreadLocal本身为key,将值存到ThreadLocalMap对象中threadLocals属性值(即ThreadLocalMap对象),然后以ThreadLocal本身为key从ThreadLocalMap对象中获取值public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}为什么ThreadLocalMap中的元素(Entry)要继承弱引用类WeakReference?
ThreadLocalMap中的key就是ThreadLocal对象本身,这时就会和Entry对象存在强引用关联而无法被GC回收,造成内存泄漏. 除非线程结束后,线程被回收了,线程中的ThreadLocalMap也跟着回收ThreadLocal什么情况下会造成内存泄漏问题?
threadLocals属性还指向了那个ThreadLocalMap对象,即存在一条强引用. 如果该线程没有被回收(例如线程池),那就存在内存泄漏问题.