HashMap
在addEntry方法中,集合长度不够时,扩充2倍。
HashMap实现原理:
基于 数组(用于区分hash值),数组里是链表(相近的hash值得K、V在一条链表上)。如图(源自他人文章):
在存储时,key的hashcode值 模以 数组长度,得到的index值(绝对在数组程长度内 index = hashcode % table.lenth),决定其存储位置(即导致集合元素时无序的),再在链表中去比较key值是否相同。
这种存储方式,检索、增、删较快。同样比单独的链表也快。即用空间换时间。
关于判断Map是否到达极限, 用size++ 来判断 ,有待弄懂??????
容量乘以负载因子的原因?????????
默认的容量是16,负载因子是0.75,相乘得12。
在HashMap构造器中,初始化容量值capacity时,获得比传入的initialCapacity大的最小的2的n次方的数。比如:initialCapacity = 10 , 则capacity = 16。 故可以,在指定容量时,指定为2的次方数,来减小系统开销。
当数组长度为2的n次幂的时候,不同的key算得得index相同的几率较小,同时能提高检索效率,避免再去链表检索。
第一次调用,new一个对象;第二次调用,直接返回对象的 算法实现。
Map的values() 没有将各value存到新的List集合中,而是将其引用存到Collection,降低内存开销。
List 实现类: ArrayList 、Vector、LinkedList 。 Vector的子类Stack,
Vector、Stack 都用 Synchronized 修饰方法,都是线程安全的。
JDK 并不推荐使用Stack ,而建议使用Deque,其实现类ArrayDeque。Deque是双端队列的数据结构(既具有队列也具有栈的特性,既能FIFO 也能 FILO),其底层和 ArrayList一样,都是通过数组实现。
Vector 和 ArrayList
同都是是实现List,底层都是通过数组来存储集合元素。
Vector是线程安全,ArrayList可以通过Collections.synchronizedList(List<T> list)实现线程安全。
ArrayList 和 LinkList
List 是一种线性表的数据结构。
ArrayList 顺序存储的线性表。
LinkList 链式存储的线性表,本质是双向链表。由于即实现List和Deque,既可以当 双向链表,也可当做栈、队列使用。
----------------------------------------
ArrayList 插入新元素时,需完成两件事: 确保底层数组元素长度大于集合元素个数;将插入点后的元素整体向后移;
ArrayList 的 remove( )
为什么要先移动,后释放被删除元素? elementDate[--size] 是末尾元素,被删除元素,怎么被移到最后了。
答:注释写错,释放的是最后一位,所引用的对象。 示例如下:
ArrayList 的 加入、删除操作,都要整体挪动数组,所以性能非常差,查询速度快
LinkList 查找指定索引的元素,开销大(得一个一个查),向某索引出插入新值,开销大(查找索引出的节点),但单纯添加节点,性能很好。
ArrayList |
LinkedList |
|
查找指定索引元素 |
性能大大优于LinkList |
需要依次搜索过去 |
在末尾添加元素 |
一般性有很好的性能,但当长度超出时,需创建1.5倍长度的新数组,但LinkedList的add()总是有较好的性能 |
可以使用addLast(),快速定位,总是性能较好 |
在指定索引添加元素 |
必须对元素“整体搬家”,超出长度得创建1.5倍长度的数组,再垃圾回收原数组 |
只需在搜索上耗性能,直接插入新元素,性能优于ArrayList |
删除指定索引元素 |
只用考虑“整体搬家”,不用考虑建新数组,性能稍优于LinkList |
与添加开销几乎完全相同 |
总结:ArrayList大部分情况性能优于LinkedList,但经常需要添加、删除时,尤其是常用add(),应考虑LinkedList |
遍历LinkedList时,不能直接使用get( ) 方法,成本太高(由链表的访问方式决定),要使用迭代器或者foreach( foreach循环的原理就是迭代器), 是直接按照地址去找数据的,将会大大提升遍历LinkedList的效率。
第一种迭代
List<Integer> list = new ArrayList<Integer>();
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
iterator.next();
}
第二种迭代
for (Iterator<String> iterator = testList.iterator(); iterator.hasNext();)
{
//String tmp = iterator.next();
}