《突破程序员基本功16课》——集合

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();

}

猜你喜欢

转载自blog.csdn.net/ImSanJin/article/details/82496159
今日推荐