集合

一、集合概述

1、集合和数组都是多个数据进行存储操作的结构,简称Java容器。此时的存储主要指的是内存层面的存储,不涉及到持久化的存储

        1.1、 数组的存储多个数据的特点:

                > 数组定义并初始化后,其长度也就确定了,而且元素类型也确定了,我们就只能操作指定类型的数据了

        1.2、 缺点:

                > 数组长度确定后,就不能对其长度进行修改

                > 数组中提供的方法非常有限,这就导致对数组中的添加、删除、插入等操作,非常不便,效率很低

                > 数组存储的数据特点是:有序的、可重复,对于无序、不可重复的需求,不能满足

        1.3、 因为数组的不足,所以引入了集合,Java集合可以分为Collection 和 Map 两种体系

                > Collection 接口: 单列数据,存储一组对象的方法和集合

                        > list: 元素有序、可重复   (ArrayList 、 LinkedList 、 Vector)

                        > set : 元素无序、不可重复  (HashSet 、 LinkedHashSet 、 TreeSet)

                > Map接口: 双列数据,保存具有映射关系的集合  (HashMap 、 LinkedHashMap 、 TreeMap 、 Hashtable 、 Properties)

                                                                     

 

二、 Collection通用方法

add(Object obj) : 添加

addAll(Collection coll) : 添加集合

int size() : 获取有效元素个数

clear() : 清空

boolean isEmpty() : 集合是否为空

 boolean contains(Object obj) : 集合中是否包含某个元素

boolean containAll(Collection coll) : 集合中是否包含集合中的所有元素        contain和containAll  都是通过调用对象的所在类的equals方法来比较元素的

boolean remove(Object obj) : 移除某个元素

boolean removeAll(Collection coll)  : 移除集合中的元素

retainAll(Collection coll) : 取两个集合的交集

boolean equals(Object obj) : 集合是否相等,当集合是ArrayList时,两个集合中的元素相同,但是顺序不一致也是false

Object toArray() : 转成对象数组    ----->        数组转换为集合 :  Arrays工具类中的 asList();

hashCode() : 获取集合对象的hash值

iterator() : 迭代器

三、迭代器

为容器而生,在不暴露对象的内部细节,访问容器中的元素

1、 方法: 

        > hasNext(): 判断集合是否还有下一个元素

        > next(): 指针下移,将下移后的集合位置上的元素返回

       > remove() : 删除指针所指集合位置上的元素

注意: 每次调用iterator() 方法都会返回一个新的迭代器对象,每个迭代器对象的初始指针都在集合首元素的前一个位置,另外,在迭代器刚刚创建的时候或还没有调用next方法时不能调用remove方法

                                                     

       2、foreach循环遍历集合元素  jdk5.0 新增的方式   foreach底层调用的也是迭代器,注意的时普通的for循环和 foreach 增强for循环的不同点,增强循环将读到的元素赋值给一个变量,修改该变量不会影响原元素

四、List接口

1、 List接口 可以认为是“动态” 数组, 它的存储是有序的,可重复的数据,主要的实现类有如下

       > ArrayList:  是List接口的主要实现类,线程不安全的,效率高, 底层使用Object[]  存储

       > LinkedList:  底层使用的是双向链表的结构进行存储,主要使用在要对集合频繁插入、删除操作的情况

       > Vector:  1.0版本出现,是古来的实现类,且是线程安全的,效率低

2、 ArrayList源码分析: jdk7.0 版本下,ArrayList底层是先创建了一个长度为10的Object[] ,当我们添加数据的时候会先判断数组的长度是否足够,不足则会扩容, 扩大为原来的1.5倍,并将原来数组中的元素复制到新的数组中

                                        ArrayList中含有一个带参的构造器,可以创建指定容量的Objec[]  数组

                                               Jdk8.0版本下,ArrayList底层不会再创建集合的时候创建一个Object[]  数组, 而是在首次添加数据的时候,创建一个长度为10的数组,并将数据添加到集合的第一个位置上,后续的添加和扩容操作和jdk1.0一样

                                               jdk7.0 的创建方式类似于单例的饿汉式,而jdk8.0中的ArrayList的对象创建类时于单例的懒汉式

       3、常用方法: 

                     增:add(Object obj)

                     删:remove(Object obj)   or   remove(int index)

                     改:set(int index , Object ele)

                     查:get(int index)

                     插:add(int index, object obj)

                     长度:size()

五、set接口

1、set接口存储的是无序的,不可重复的,类时于数学中的“ 集合 ”, 主要的实现类如下

      > HashSet:作为set接口的主要实现类,线程不安全的,可以存储null值

             > LinkedHashSet: 作为HashSet的子类,遍历其内部数据时,可以按照添加的顺序遍历

       >TreeSet:可以按照添加对象的指定属性,进行排序

       2、理解set的无序性和不可重复性:这里的无序性不等于随机性,存储的数据在底层数组并非按照数组索引的顺序添加,而是根据数据的哈希值

                                                                不可重复性就是指集合中的元素不能重复,按照equals() 判断,不能返回true,即相同的元素只能添加一个

                     添加元素的过程,以HashSet为例:

                            假设我么向HashSet中添加元素 a ,首先调用 元素a 所在类的hashCode()  ,计算出元素a 在底层数组中存放的位置,如果元素a 要存放的位置没有元素,则添加成功

                                   如果元素a 要存放的位置已经存在元素b ,比较元素a 和元素b 的哈希值,如果两个元素的哈希值不同,则元素a 添加成功

                                   如果两个元素的哈希值相同,则调用元素a 所在的equals()  ,如果equals() 返回true , 则元素a 添加失败 ,反之, 则添加成功

                                                                                                           

 

                     LinkedHashSet: 在HashSet的基础上给每个元素添加了前驱节点和后继节点,让频繁插入、删除等操作更加的高效

六、 Map

1、Map: 双列数据,存储 key - value 对的数据,类似于函数

       > HashMap: 作为Map的主要实现类 , 线程不安全,效率高, 可以存储null的 key 和value

              > linkedHashMap: 遍历集合的时候可以按照添加顺序实现遍历,因为在原有的HashMap底层结构上,添加了一对指针,指向前一个和后一个 元素

              > TreeMap : 保证按照添加的key - value 对进行排序,实现排序遍历,此时考虑key的自然排序或定制排序

              > Hashtable : 作为古老的实现类 , 线程安全的 ,效率低,不可以存储null的 key 和 value

                     > properties : 常用来处理配置文件, key 和value 都是String类型

       2、 Map的结构理解

              Map中的key 是无序的、不可重复的,使用set存储 所有的key   ---->  故key所在的类要重写equals() 和 hashCode()

              Map中的value是无序的,可重复的,使用Collection存储所有的value  ---->  故value所在的类要重写equals()

              一个键值对key - value 就代表着一个entry,entry是无序的,不可重复的,使用set 来存储所有的entry

       3、HashMap底层: 数组 + 链表 (jdk 7.0及之前)

                                        数组 + 链表 + 红黑树 (jdk 8)

              底层实现原理:

                     > JDK 7.0, HashMap map = new HashMap();  实例化后,底层会创建一个长度为16的Entry[] 数组,当我们添加数据(key1 - value1)时, 首先调用key1所在类的hashCode() 方法,通过某种算法得到该键值对在 Entry数组中的位置

                                                 如果该位置上没有元素则添加数据(key1 - value1)成功

                                                 如果该位置上有元素,也就是说该位置上已经有一个或多个数据(以链表的形式存在),比较key1 和 这些元素的哈希值

                                                        如果哈希值不相同,则添加数据(key1 - value1)成功

                                                        如果哈希值相同,则继续比较,调用key1所在类的equals() 方法

                                                               如果equals() 返回false,则添加数据(key1 - value1)成功,返回true则将用value1替换原来的value值

                     扩容问题:当数组的长度大于临界值才会扩容(为什么要提前扩容? --- >  尽可能使链表的数量少), 默认的扩容方式是扩容为原来的2倍,并将原来的数据复制过来

                     > JDK 8,于7不同的是,在实例化HashMap的时候,底层没有创建一个长度为16的数组,而是在调用put() 方法的时候才创建长度为16的数组,该数组不再是Entry[] 而是 Node[]

                                          7底层的结构是 : 数组 + 链表, 8底层的结构是: 数组 + 链表 + 红黑树( 当数组的某个索引位置上的元素以链表的形式存在的数据个数 > 8,且当前数组的长度 > 64时,此时索引位置上的所有数据改为使用红黑树存储 )

                     改为红黑树的原因: 便于遍历,提高查找的效率

              HashMap源码的重要常量:

                            DEFAULT_INITIAL_CAPACITY : HashMap的默认容量,16

                            DEFAULT_LOAD_FACTOR:HashMap的默认加载因子  0.75

                            threshold:扩容的临界值,=容量*填充因子  12

                            TREEIFY_THRESHOLD:Bucket中链表长度大于该默认值,转化为红黑树

                            MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量  64

       4、LinkedHashMap:

                     对HashMap中的node进行类继承,并添加了before 和after ,进而直到前一个元素和下一个元素的位置, 有利于对 插入 、 删除等的操作

       5、 常用方法

              > 增 : put(Object key , Object value)

              > 删 : remove(Object key)

              > 查 : get(Object key)

              > 改 : put(Object key, Object value)

              > 遍历 :keySet() 、 values() 、 entrySet()

      6、TreeMap:

                  TreeMap中添加key  -  value,要求key来自同一个类,该类还要提供 自然排序 或 定制排序,因为要按照key进行排序

 

 

 

 

 

 

 

 

 

 

              

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值