Java8新特性——集合底层源码实现的改变

1394518-20181025171324162-1483936762.png

ArrayList 源码分析:

jdk7:

ArrayList list = new ArrayList();//初始化一个长度为10的Object[] elementData
sysout(list.size());//返回存储的元素的个数:0
list.add(123);
list.add(345);
...
当添加第11个元素时,需要扩容,默认扩容为原来的1.5倍。还需要将原有数组中的数据复制到新的数组中。
删除操作:如果删除某一个数组位置的元素,需要其后面的元素依次前移。
remove(Object obj) / remove(int index)

jdk8:

ArrayList list = new ArrayList();//初始化一个长度为0的Object[] elementData
sysout(list.size());//返回存储的元素的个数:0
list.add(123);//此时才创建一个长度为10的Object[] elementData
list.add(345);
...
当添加第11个元素时,需要扩容,默认扩容为原来的1.5倍。还需要将原有数组中的数据复制到新的数组中。
开发时的启示:

  1. 建议使用:ArrayList list = new ArrayList(int length);
  2. jdk8延迟了底层数组的创建:内存的使用率;对象的创建更快

    LinkedList 源码分析

    LinkedList:底层使用双向链表存储添加的元素
    void linkedlist(E e) {
    final Node l = last;
    final Node newNode = new Node<>(l, e, null);
    last = newNode;
    if (l == null)
    first = newNode;
    else
    l.next = newNode;
    size++;
    modCount++;
    }
    内部类体现:
    private static class Node {
    E item;
    Node next;
    Node prev;
    }

    HashMap

    jdk1.7

    HashMap map = new HashMap();//底层创建了长度为16的Entry数组
    向HashMap中添加entry1(key,value),需要首先计算entry1中key的哈希值(根据key所在类的hashCode()计算得到),此哈希值经过处理以后,得到在底层Entry[]数组中要存储的位置i.如果位置i上没有元素,则entry1直接添加成功。如果位置i上已经存在entry2(或还有链表存在的entry3,entry4),则需要通过循环的方法,依次比较entry1中key和其他的entry是否equals.如果返回值为true.则使用entry1的value去替换equals为true的entry的value.如果遍历一遍以后,发现所有的equals返回都为false,则entry1仍可添加成功。entry1指向原有的entry元素。
    默认情况下,如果添加元素的长度 >= DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR (临界值threshold默认值为12)且新要添加的数组位置不为null的情况下,就进行扩容。默认扩容为原有长度的2倍。将原有的数据复制到新的数组中。

    jdk1.8

    1.HashMap map = new HashMap();//默认情况下,先不创建长度为16的数组。
    2.当首次调用map.put()时,再创建长度为16的数组
    3.当数组指定索引位置的链表长度>8时,且map中的数组的长度> 64时,此索引位置上的所有entry使用红黑树进行存储。而jdk 7 中没有红黑树结构
    4.新添加的元素如果与现有的元素以链表方式存储的时候:“七上八下”:jdk7:新添加的当链表头,jdk8:新添加的当链表尾

    HashMap的存储结构

    JDK 7及以前版本:HashMap是数组+链表结构(即为链地址法)
    1394518-20181025213824135-594083698.png
    JDK 8版本发布以后:HashMap是数组+链表+红黑树实现。
    1394518-20181025213856258-569883305.png

    负载因子值的大小,对HashMap的影响

    负载因子的大小决定了HashMap的数据密度,负载因子越大密度越大,发生碰撞的几率越高,数组中的链表越容易长,
    造成查询或插入时的比较次数增多,性能会下降。负载因子越小,就越容易触发扩容,数据密度也越小,意味着发生碰撞的几率越小,数组中的链表也就越短,查询和插入时比较的次数也越小,性能会更高。但是会浪费一定的内容空间。而且经常扩容也会影响性能,建议初始化预设大一点的空间

转载于:https://www.cnblogs.com/nnxud/p/9851710.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值