数据结构与集合源码

1.数据结构

  • 数据结构的研究对象:
  • ①数据间的逻辑关系(集合关系、一对一、一对多、多对多)
  • ②数据的存储结构(或物理结构)
    • 角度一:顺序结构、链式结构、索引结构、哈希结构
    • 角度二:线性表(一维数组、链表、栈、队列)、树(二叉树、B+树)、图(多对多)、哈希表(HashMap、HashSet)
    • ③相关运算
  • 树(了解)
  • 相关数据结构的核心Node的设计(单向链表、双向链表、二叉树。栈、队列)(理解)

2.List接口下的实现类的源码的剖析

【面试题】ArrayList、Vector、LinkedList的三者的对比?

  • 层次一:

     |----子接口:List:有序的可以重复的数据("动态"数组)
            |---- ArraysList:List主要的实现类;线程不安全,效率高;底层使用Object[]数组存储
                             在添加数据,查找数据时,效率较高;在插入,删除数据时,效率较低
            |----- LinkedLis:底层使用双向链表的方式进行存储;在对集合中的数据进行频繁删除和插入操作时建议使用此类
                             在添加数据,查找数据时,效率较低;在插入,删除数据时,效率较高
            |----Vector:List的古老的实现类;线程安全的,效率低;底层使用Object[]数组存储
    
  • 层次二:查看相关api的源码


一、ArrayList
1. ArrayList的特点:
>实现了List接口,存储有序的可以重复的数据
>底层使用Object[]数组存储
>线程不安全的


2. ArrayList源码解析:
2.1 jdk7版本:(以jdk1.7.0_07为例)

ArrayList<String> list = new ArrayList<>(); //底层会初始化数组Object[] elementData=new Object[10];默认长度为10

list.add("AA"); //elementData[0]="AA";
list.add("BB");//elementData[1]="BB";
....
当要添加第11个元素的时候,底层的elementData数组已满,则需要扩容,默认扩容为原来长度的1.5,并将原有数组
中的元素复制到新的数组中.



2.2 jdk8版本:(以jdk1.8.0_271为例)
ArrayList<String> list = new ArrayList<>(); //底层会初始化数组Object[] elementData=new Object[]{};

list.add("AA"); //首次添加元素时,会重新初始化数组elementData=new Object[10];elementData[0]="AA";
list.add("BB");//elementData[1]="BB";
....
当要添加第11个元素的时候,底层的elementData数组已满,则需要扩容,默认扩容为原来长度的1.5,并将原有数组
中的元素复制到新的数组中

小结:
jdk7的版本中:ArrayList类似于饿汉式
jdk8的版本中:ArrayList类似于懒汉式



二、Vector
1. Vector的特点:
>实现了List接口,存储有序的可以重复的数据
>底层使用Object[]数组存储
>线程安全的



2. Vector源码解析:(以jdk1.8.0_271为例)

Vector v= new Vector(); //底层初始化数组,长度为10 Object[] elementData=new Object[10];
v.add("AA");//elementData[0]="AA";
v.add("BB");//elementData[1]="BB";
...
当添加到11个元素时,需要扩容,默认扩容到原来的2倍




三、LinkedList
1. LinkedList的特点:
>实现了List接口,存储有序的可以重复的数据
>底层使用双向链表数组存储
>线程不安全的



2. LinkedList在jdk8中的源码解析:

LinkedList<String> list = new LinkedList<>();//底层也没做啥
list.add("AA");//将"AA"封装到一个Node对象1中,List对象的属性first,last都指向此Node对象1
list.add("BB");//将"BB"封装到一个Node对象2中,对象1和对象23构成一个双向链表,同时last指向Node对象2

...
因为LinkedList使用的是双向链表,不需要考虑扩容问题


LinkedList内部声明
  private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;
}

3. LinkedList是否存在扩容问题?NO!


四、启示与开发建议
1. Vector基本不使用了
2. ArrayList底层使用的是数组结构,查找和添加(尾部添加效率高),时间复杂度为O(1 )
                               删除和插入操作效率低,时间复杂度为O(n)
   LinkedList底层使用双向链表结构,删除和插入的操作效率比较高,时间复杂度为O(1)
                                查找和添加(尾部添加效率低),时间复杂度为O(n)(有可能添加是O(1))
3. 在选择了ArrayList的前提下,new ArrayList():底层创建长度为10的数组
                            new ArrayList(int capacity):底层创建指定长度的数组
   如果开发中,大体确认数组的长度,则推荐使用 ArrayList(int capacity)这个构造器,避免了底层的扩容,复制数组的操作,效率相对来说高一些



3.Map接口下的实现类的源码剖析

  • (必须掌握)HashMap的底层源码的剖析

添加/修改的过程:(key1,value1)添加到当前的map中:
首先,需要调用key1所在类hashCode()方法,计算key1对应的哈希值1,此哈希值1经过某种算法(hash(哈希值1))之后,得到哈希值2
哈希值2在经过某种算法(indexFor())之后,就确定了(key1,value1)其在数组table中的索引位置i
  1.1如果此说索引位置i的数组上没有元素,(key1,value1)就添加成功   ----情况1
  1.2如果此索引位置i数组上有元素(key2,value2),则需要继续比较key1和key2的哈希值2   -----哈希冲突
          2.1如果key1的哈希值2与key2的哈希值2不相同,(key1,value1)添加成功  ----情况2
          2.2如果key1的哈希值2与key2的哈希值2相同,则需要继续比较key1和key2的equals(),要调用key1所在类的equals(),将key2作为参数传递进去
               3.1调用equals(),返回false:(key1,value1)添加成功   ----情况3
               3.2调用equals(),返回true:则认为key1和key2是相同的,默认情况下,value1替换原有的value2

说明:情况1:(key1,value1)存放到数组的索引i的位置
     情况2,情况3:(key1,value1)元素与现有的(key2,value2)构成单向链表结构,(key1,value1)指向(key2,value2)


随着我们不断地添加元素,在满足如下的条件的情况下,会考虑扩容:
(size >= threshold)  && (null !=table[i])
当元素的个数达到临界值(-> 数组的长度 * 加载因子),就考虑扩容,默认的临界值=16*0.75--->12
默认扩容为原来的2
  • (熟悉)LinkedHashMap的底层源码的剖析
二、LinkedHashMap
1. LinkedHashMapHashMap 的关系:
>LinkedHashMapHashMap的子类
>LinkedHashMapHashMap使用的数组+单向链表+红黑树的基础上,又增加了一对双向链表,记录添加的(key,value)的
先后顺序,便于我们遍历所有的key-value
  • (了解)HashSet、LinkedHashSet的底层源码剖析
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

死磕java的孤行者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值