Java集合(集合类与关系图)

目录

文章内容

Java中的集合关系图

Java中的集合类

1.ArrayList、 LinkedList、 Vector三者的异同?

1.1ArrayList:

1.2LinkedList:

1.3Vector:

2.ArrayList的源码分析

2.1Jdk7情况下:

2.2JDK8中ArrayList的变化:

3.LinkedList的源码分析

4.Set的无序性和有序性

5.Map结构的理解

6.HashMap由什么组成?

6.1这两个阈值为什么不相同呢?

7.HashMap的底层实现原理,以JDK7为例

7.1JDK8相较于JDK7在底层实现方面的不同

7.2HashMap和HashTable区别

7.3hash冲突的解决办法?

7.4HashMap往链表里插入节点的方式?

Collection和Collections的区别


文章内容

从为什么要用集合开始思考:

1.集合,数组都是对多个数据进行存储操作的结构,简称Java容器。

2.数组在存储多个数据方面的特点:

>一旦初始化以后,长度就确定了。

>数组一旦定义好,其元素的类型也就确定了。我们也就只能操作指定类型的数据了。
比如: String[ ] arr;int[] arr1;Object[] arr2;

3.数组在存储多个数据方面的缺点:

>一旦初始化以后,其长度就不可修改。

>数组中提供的方法非常有限,添加删除插入数据等操作,非常不便,效率不高。
>获取数组中实际元素的个数的需求,数组没有现成的属性或方法。
>数组存储数据的特点:有序,可重复,对于无序,不重复的需求,不能满足。

所以集合可以解决问题。

Java中的集合关系图

1.      /----Collection接口:单列集合,用来存储一个一个的对象
          / ----List接口:存储有序的、可重复的数据。-->“动态”数组
             /----ArrayList、LinkedList、 Vector

        /----Set接口:存储无序的、不可重复的数据-->高中讲的*集合
              / ----Hashset、LinkedHashset、 Treeset

2.      /----Map接口:双列集合,用来存储一对(key - value)一对的数据-->高中函数: y = f(x)
              /----HashMap、LinkedHashMap、TreeMap、Hashtable、Properties 

Java中的集合类

1.ArrayList、 LinkedList、 Vector三者的异同?

相同点:三个类都是实现了List接口,存储数据的贴点相同:存储有序,可重复的数据。

不同点: 

1.1ArrayList:

作为List接口的主要实现类;线程非安全;效率高;底层使用Object[ ] elementData(数组)存储,扩容为1.5倍。

1.2LinkedList:

对于频繁的插入,删除操作使用此类效率比ArrayList效率高;底层使用双向链表存储。

1.3Vector:

作为List接口的古老实现类;线程安全,因此效率低,底层使用Object [ ]elementData存储,扩容为2倍。 

2.ArrayList的源码分析

2.1Jdk7情况下:

ArrayList list = new ArrayList();     //底层创建了长度是10的object[]数组eLementData
list.add(123);                                 //elementData[e] = new Integer(123);
                ...
list.add(11);                                   //如果此次的添加导致底层eLementData数组容量不够,则扩容。
默认情况下,扩容为原来的容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中。

结论:假如数组容量确定时,为了避免扩容开销,建议开发中使用带参的构造器:ArrayList list = new ArrayList(int capacity)

2.2JDK8中ArrayList的变化:

ArrayList list = new ArrayList();   //底层object[] elementData初始化为{}.并没有创建数组。
list.add(123);                   //第一次调用add()时,底层才创建了长度10的数组,并将123添加到elementData。

3.LinkedList的源码分析

LinkedList list = new LinkedList();内部声明了Node类型的first和Last属性,默认值为null
list.add (123);//将123封装到Node中,创建了Node对象。
其中,Node定义为:
                private static cLass Node<E>{
                    E item;
                    Node<E> next;
                    Node<E> prev;
                    Node (Node<E> prev, E element, Node<E> next){
                    this.item = element;
                    this.next = next;
                    this.prev = prev;
                    }
                }

4.Set的无序性和有序性

1.无序性:不等于随机性。存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值。
2.不可重复性:保证添加的元素按照equals()判断时,不能返回true.即:相同的元素只能添加一个。

5.Map结构的理解

Map中的key:无序的、不可重复的,使用set存储所有的key--->key所在的类要重写equals()和hashcode()。
Map中的value:无序的、可重复的,使用Collection存储所有的value--->vaLue所在的类要重写equals()。
一个键值对: key-value构成了一个Entry对象。
Map中的entry:无序的、不可重复的,使用set存储所有的entry。

6.HashMap由什么组成?

数组+单链表,jdk1.8以后又加了红黑树,当链表节点个数超过8个(m默认值)以后,开始使用红黑树,使用红黑树一个综合取优的选择,相对于其他数据结构,红黑树的查询和插入效率都比较高。而当红黑树的节点个数小于6个(默认值)以后,又开始使用链表。

6.1这两个阈值为什么不相同呢?

主要是为了防止出现节点个数频繁在一个相同的数值来回切换,举个极端例子,现在单链表的节点个数是9,开始变成红黑树,然后红黑树节点个数又变成8,就又得变成单链表,然后节点个数又变成9,就又得变成红黑树,这样的情况消耗严重浪费,因此干脆错开两个阈值的大小,使得变成红黑树后“不那么容易”就需要变回单链表,同样,使得变成单链表后,“不那么容易”就需要变回红黑树。

7.HashMap的底层实现原理,以JDK7为例

在实例化以后,底层创建了长度是16的一维数组Entry[ ] table
    ...可能已经执行过多次put. . .
    map.put( key1, value1):
    首先,调用key1所在类的hashCode()计算key1哈希值,此哈希值经过某种算法计算以后,得到在Entry数组中的存放位置。
    如果此位置上的数据为空,此时的key1-value1添加成功。----情况1
    如果此位置上的数据不为空,(意味着此位置上存在一个或多个数据(以链表形式存在)),比较key1和已经存在的一个或多个数据的哈希值:
            如果key1的哈希值与已经存在的数据的哈希值都不相同,此时key1-value1添加成功。----情况2
            如果key1的哈希值和已经存在的某一个数据(key2-value2)的哈希值相同,继续比较:调用key1所在类的equals(key2)方法,比较:
                如果equals()返回false:此时key1-value1添加成功。----情况3
                如果equals()返回true:使用vaLue1替换value2。

    补充:关于情况2和情况3:此时key1-value1和原来的数据以链表的方式存储。

    在不断的添加过程中,会涉及到扩容问题,默认的扩容方式:扩容为原来容量的2倍,并将原有的数据复制过来。

7.1JDK8相较于JDK7在底层实现方面的不同

    1. new HashMap():底层没有创建一个长度为16的数组
    2. jdk8底层的数组是:Node[],而非Entry[]
    3.首次调用put()方法时,底层创建长度为16的数组
    4. jdk7底层结构只有:数组+链表。jdk8中底层结构:数组+链表+红黑树
        当数组的某一个索引位置上的元素以链表形式存在的数据个数>8且当前数组的长度>64时,
        此时此索引位置上的所有数据改为使用红黑树存储。

        DEFAULT_INITIAL_CAPACITY : HashMap的默认容量,16
        DEFAULT_LOAD_FACTOR: HashMap的默认加载因子:0.75
        threshold:扩容的临界值,=容量*填充因子:16* 0.75 =>12
        TREEIFY_THRESHOLD: Bucket中链表长度大于该默认值,转化为红黑树:8
        MIN_TREEIFY_CAPACITY:_桶中的Node被树化时最小的hash表容量:64

7.2HashMap和HashTable区别

    1).HashTable的方法前面都有synchronized来同步,是线程安全的;HashMap未经同步,是非线程安全的。
    2).HashTable不允许null值(key和value都不可以) ;HashMap允许null值(key和value都可以)。
    3).HashTable有一个contains(Object value)功能和containsValue(Object value)功能一样。
    4).HashTable使用Enumeration(枚举)进行遍历;HashMap使用Iterator(迭代器)进行遍历。
    5).HashTable中hash数组默认大小是11,增加的方式是old*2+1;HashMap中hash数组的默认大小是16,而且一定是2的指数。(1.提高计算效率2.动态扩容后从新计算哈希位置时能均匀分布元素)
    6).哈希值的使用不同,HashTable直接使用对象的hashCode; HashMap重新计算hash值,而且用与代替求模。

7.3hash冲突的解决办法?

1.开放地址法   2.链地址法。

7.4HashMap往链表里插入节点的方式?

jdk1.7以前是头插法,jdK1.8以后是尾插法,因为引入红黑树之后,就需要判断单链表的节点个数(超过8个后要转换成红黑树),所以干脆使用尾插法,正好遍历单链表,读取节点个数。也正是因为尾插法,使得HashMap在插入节点时,可以判断是否有重复节点。

Collection和Collections的区别

Collection是一个集合接口,ArrayList,HashSet等集合类是实现该接口。

java.util.Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。

  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我想要的我会认真

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

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

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

打赏作者

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

抵扣说明:

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

余额充值