JAVA-集合

集合

要想深刻理解集合知识,必须明确“集合”的存在是为了解决什么样的问题?

如何解决该类问题?在将大问题细分的过程中,“集合”为了一一解决小问题,又一步步细分成哪些小知识,他们之间构成怎样的逻辑关系?

集合--存在的意义?

O-O思想中,万物皆对象。集合的意义就是: 对对象的存储。

区别于Array, 集合更强大,体现在,集合是动态的,而Array是静态的

集合的第一次划分

Collection和Map的区别在于容器中每个位置保存的元素个数:

1) Collection 每个位置只能保存一个元素(对象)

2) Map保存的是"键值对",就像一个小型数据库。我们可以通过"键"找到该键对应的"值",键值都可以是任何应用类型的数据

Collection

1. Interface Iterable

迭代器接口,Collection接口的父接口,在Collection这一房份,都实现了Iterable接口。都可以通过iterator()方法创建迭代器对象,进而遍历集合

2. Collection

该房份的第一代创始人,祖先。 是一个接口,只提供规范定义,不能被实例化。意义就是代表一组Object对象的集合

2.1 List

List接口,解决数组的局限性,其最接近数组。

特点: 元素有序且可重复,每个元素都有其对应的顺序索引

2.1.1 类 ArrayList

本质上是对象引用的一个“变长”数组

2.1.2 类LinkedList

双向链表,内部没有声明数组,而是定义了Node类型的first和last, 用于记录首末元素。同时,定义内部类Node,作为LinkedList中保存数据的基本结构。Node除了保存数据,还定义了两个变量: prev变量记录前一个元素的位置 ,next变量记录下一个元素的位置

2.1.3 类Vector

大多数操作与ArrayList 相同,区别之处在于Vector是线程安全的。

2.1.4 类Stack

Vector的子类,模拟“栈”这种数据结构。


List三个实现类的特点:

数组方便遍历查找 ---> ArrayList

链表方便增删Node---> LinkedList

为了线程安全--->vector

2.2 Queue

集合的队列实现: 先进先出,不予许随机访问队列中的元素

2.2.1 PriorityQueue

以自定义的优先级作为先后,而不以进入Queue的顺序作为先后

2.2.2 Deque

接口,是一个双端队列:两端都可以实现进出操作,所以它可以被改造成栈或者队列

2.2.3 ArrayDeque

是一个基于数组的双端队列,和ArrayList类似,它们的底层都采用一个动态的、可重分配的Object[]数组来存储集合元素,当集合元素超出该数组的容量时,系统会在底层重新分配一个Object[]数组来存储集合元素

2.3 set 接口

接口,元素无序,不可重复

使用equals()方法判断元素是否相等

2.3.1 HashSet 类

Set的典型实现,拉链法数据结构

HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取、查找、删除 性能。 其中hashCode() 充当hash函数,计算出元素的hashCord值作为下标。 使用equals()判断元素值是否相等,进而决定添加是否成功。

原则:相等的对象必须具有相等的散列码


2.3.2 LinkedHashSet 类

HashSet的子类,在HashSet的数据结构基础上,增加双向链表将元素按照插入顺序连接。增删性能降低,但迭代访问元素性能很高

2.3.3 SortedSet 接口

此接口主要用于排序操作,即实现此接口的子类都属于排序的子类

2.3.4 TreeSet

TreeSet是SortedSet接口的实现类,TreeSet可以确保集合元素处于排序状态

底层使用红黑树结构存储数据,两种排序方法:自然排序,定制排序

2.3.5 EnumSet

EnumSet是一个专门为枚举类设计的集合类,EnumSet中所有元素都必须是指定枚举类型的枚举值,该枚举类型在创建EnumSet时显式、或隐式地指定。EnumSet的集合元素也是有序的,它们以枚举值在Enum类内的定义顺序来决定集合元素的顺序


Set子接口子类的特点:

1.HashSet: 将哈希表原理应用在集合中

2.LinkedHashSet: 在HashSet上增加双向链表,将元素按插入顺序连接,遍历更方便

3.SortSet接口: 实现此接口的子类都属于排序的子类

4.TreeSet实现了SortSet接口:底层红黑树,确保元素处于排序状态

5.EnumSet: 元素皆为统一类的枚举对象,实现了排序

Map

意义:实现两组对象之间的映射关系

特点: 1.Map中的键和值都可以是对象.一个键只对应唯一的值(映射)

1. HashMap

1.1是什么:

每一个键值对作为一个实体,在存储中视为Node.

将Key作为输入,应用HashSet的实现方法,构建Hash表,只不过存储的是键值对实体. HashMap的键和值均可以使用null

1.2 key-value:

1.Key构成的集合是Set: 无序的,不可重复的。所以,key所在的类要重写:equals(), 和hashCode()

2. Vaule构成的集合是Collection: 无序,可以重复的。所以value所在的类要重写:equals()

1.3 数据结构--->Node数组+Node链

1.创建长度为Capacity的Entry数组。(Capacity称为容量)

2.数组中可以存放元素的位置称为“桶” (bucket),数组元素有下标,可以快速索引

3.bucket中存放实体Node,因为Node带有引用变量,所以数组中的元素可以作为链表的head

1.4 添加元素entry1(key , value):

1. 计算entry1中key的哈希值(根据 key所在类的hashCode()计算得到),此哈希值经过处理以后,得到在底层Entry[]数组中要存储的位置i。

2.如果位置i上没有元素,则entry1直接添加成功。

3.如果位置i上 已经存在entry2(或还有链表存在的entry3,entry4),则需要通过循环的方法,依次 比较entry1中key和其他的entry。

4.如果彼此的Hash值不同,则直接添加成功

5.如果Hash值相同,继续比较二者是否equals

6.如果返回值为true,则使用entry1的value 去替换equals为true的entry的value

7.如果遍历一遍以后,发现所有的equals返回都 为false,则entry1仍可添加成功。entry1指向原有的entry元素。

注意点:

1.形成链表结构时,新添加的key-value对在链表的尾部(七上八下)

2.当数组指定索引位置的链表长度>8时,且map中的数组的长度> 64时,此索引位置 上的所有key-value对使用红黑树进行存储。

总结:1.是否已经存在元素 2.Hash值 3.key对象

1.5 扩容

临界值:Capacity*loadFactor  达到临界值时,数组大小扩大到两倍,Capacity*2.    数组大小改变后,需要重新计算每个元素的位置,这个过程非常消耗性能,所以往往要恰当的预设元素的个数来提高性能。

1.6 树形化

当HashMap中的其中一个链的对象个数如果达到了8个,此时如果capacity没有 达到64,那么HashMap会先扩容解决,如果已经达到了64,那么这个链会变成树,结点类型由Node变成TreeNode类型。当然,如果当映射关系被移除后, 下次resize方法时判断树的结点个数低于6个,也会把树再转为链表。


2.LinkedHashMap

同LinkedHashSet的功能

3.TreeMap

同TreeSet的功能,是在Key上进行排序

4.Hashtable

功能类似于HashMap,但是不能使用空值,HashTable是线程安全的

5.Properties

是Hashtable的子类,用于处理属性文件,键值都是String类型

存取数据时,建议使用setProperty(String key,String value)方法和 getProperty(String key)方法

工具类(注意: 加了s)

Collections

Collections 是一个操作 Set、List 和 Map 等集合的工具类

Collections 中提供了一系列静态的方法对集合元素进行:排序、查询和修改等操作, 还提供了对集合对象设置不可变、对集合对象实现同步控制等方

Arrays

操作数组的工具类

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容