集合笔记

来源:互联网 发布:linux用户目前已登录 编辑:程序博客网 时间:2024/05/21 04:21

【ArrayList LinkedList Vector】

Vector对于ArrayList,因为同步而引起的性能差别并不明显;

LinkedList是循环双向链表,无论是否为空,总包含一个header表项:

|——————————————————————>

header ——> ele1 ——-> ele2 ——> ele3

      &lt;<span class="literal" style="color: #268bd2;">-</span><span class="literal" style="color: #268bd2;">-</span><span class="literal" style="color: #268bd2;">-</span><span class="literal" style="color: #268bd2;">-</span><span class="literal" style="color: #268bd2;">-</span>       &lt;<span class="literal" style="color: #268bd2;">-</span><span class="literal" style="color: #268bd2;">-</span><span class="literal" style="color: #268bd2;">-</span><span class="literal" style="color: #268bd2;">-</span><span class="literal" style="color: #268bd2;">-</span>         &lt;<span class="literal" style="color: #268bd2;">-</span><span class="literal" style="color: #268bd2;">-</span><span class="literal" style="color: #268bd2;">-</span><span class="literal" style="color: #268bd2;">-</span>

<—————————————————————-|

增加元素到表尾,ArrayList 优于 LinkedList:

ArrayList的扩容最终调用System.arraycopy()方法;

数组是连续的,ArrayList只有在扩容时才会低效一些;

而链表,虽然无须扩容,但新建对象和大量赋值操作会低效;

插入元素到任意位置,LinkedList优于ArrayList:

因为Array的连续性,每次插入操作都需要是数组重排;

LinkedList在任意位置插入和尾部插入是一样的;

删除任意位置元素,ArrayList尾部删除、LinkedList在头部删除和尾部删除这三个都是高效的,其他的都是低效的:

ArrayList任意位置删除需要重排数组;

LinkedList删除元素并不是从头到尾找,而是头尾分别找(循环双向链表),所以只有中间元素的删除是低效的;

迭代器本质的遍历对于ArrayList和LinkedList来说效率是一样好的:

for-each本质就是迭代器实现,但如果不直接显式用迭代器,编译器将for-each转换为迭代器的时候总是不够聪明,导致for-each比迭代器性能略差;

随机访问遍历,ArrayList获得最高表现,LinkedList获得最低表现;

【HashMap Hashtable】链表root元素组成的数组

Hashtable和HashMap的性能几乎一样,差异有:

Hashtable是同步的,HashMap不是线程安全的;

Hashtable不允许key或value是null,HashMap允许;

Hashtable和HashMap的hash算法和hash值到内存的索引算法不同;

HashMap的底层存储就是个数组,hash值索引到内存地址就是索引到数组下标:

Object.hashCode是native方法;

通过将hash值和数组长度按位取与直接得到数组下标;

HashMap实际上是一个链表数组,每个数组元素又是个链表的root节点,hashCode冲突的项成链表存储:

Entry 1 | key

Entry 2 ——-> | value

… | next

Entry n | hash

Entry被存储在数组里,重复hashCode的Entry之间又是链表链接;

HashMap的高效源自对数组随机访问的高效,如果hashCode冲突越大,则HashMap越趋于几个链表,随机访问的性能低下;

判断hash冲突的条件:

e.hash == hash && (e.key == key || key.equals(e.key))

HashMap的容量参数有两个:数组长度和负载因子;

【负载因子】 = 元素个数 / 内部数组的总大小, 默认是0.75;如果元素个数超过了负载因子规定的阈值,则数组就会扩容;

存储同量的元素,负载因子越大,数组空间占用越小,hash冲突越明显;

【LinkedHashMap】此有序非彼有序:元素最后访问顺序和元素插入顺序

所谓的HashMap无序,是说元素插入HashMap之后,由于HashCode的无序映射,使得元素遍历结果的顺序和插入的顺序不一样,从这个有序的意义上说,ArrayList, Vector, LinkedList都是有序的;

而LinkedHashMap仅仅是实现了上述的有序,并不是TreeMap的自动排序;

LinkedHashMap有两种次序:元素最后访问顺序和元素插入顺序:

public LinkedHashMap(int capacity, float loadFactor, boolean accessOrder);

accessOrder == true: 元素最后访问顺序;

accessOrder == false: 元素插入顺序;

元素最后访问顺序对于缓存池淘汰元素很有意义,但要慎用,以防ConcurrentModificationException,因为LinkedHashMap.get()会引起元素重排序:

m = new LinkedHashMap

0 0
原创粉丝点击