集合
为什么需要集合
Java是一门面向对象的语言,自然就少不了去处理对象。
为了方便操作多个对象,我们就需要把这多个对象存储起来
想要存储多个对象(变量),我们就需要一个容器
我们常用的容器有StringBuffered、对象数组,但是数组的长度不可变的
这时候我们就需要用到集合了。
数组和集合的区别
- 长度的区别:数组的长度是固定的,集合的长度是可变的
- 元素的数据类型:数组支持基本的数据类型,也支持引用类型,集合只支持引用类型(存入一个int类型,它会自动装箱成Integer)
- 元素的内容:数组只能存储一种类型,集合可以存储多种类型(一般也只存储一种类型的数据)
collection的由来
集合可以存储多种元素,我们对多种元素也有不同的需求
例如:多个元素不能有相同的,多个元素能够按照某种规则排序
针对不同的需求,java提供了很多个集合类,多个集合类的数据结构不同
但是结构不重要,重要的是能够存储东西,能够判断、获取
最终形成集合的体系----collection
collection的方法
迭代器
我们可以在collection的源码中发现,它继承了Iterable接口,有iterator()方法,iterator()方法的返回值是iterator,iterator也是一个接口,它有三个方法:
- hasNext():判断集合内是否有元素
- next():通过此方法获取元素并移动到下一位置
- remove()
但是没有找到对应的实现方法,在他的子类ArrayList中找到了iterator实现的身影,它在ArrayList中是以内部类的方式实现的,并且从源码得知:iterator实际上就是在遍历集合。
我们遍历集合中的元素,都可以使用iterator
迭代器为什么不定义成一个类,而是一个接口
假设迭代器定义的是一个类,这样我们就可以创建该类的对象,调用该类的方法来实现集合的遍历,但是,java中提供了很多个集合类,而这些集合类的数据结构是不同的,所以存储的方式和遍历的方式行该是不同的,进而他们遍历的方式也应该是不同的,最终就没有定义迭代器类
而无论是哪种集合,都应该具备获取元素的操作,最好再辅助于判断功能,这样在获取前先判断,更不容易出错。也就是说,判断功能和获取功能应该是遍历一个集合所具备的,而没有集合的方式又不太一样,所以我们把这两个功能提取出来,并不提供具体实现,这种方式就是接口。
真正的实现,是在子类中以内部类的方式实现的
常用集合分类
collection接口的子类:对象的集合(单列集合)
-
List接口:ArrayList:底层数据结构动态数组,查询快,增删慢,元素可重复,线程不安全
LinkedList:底层数据结构双向链表,查询慢,增删快,元素可重复,线程不安全
Vector:底层数据结构动态数组,查询快,增删慢,元素可重复,线程安全
Stack:Vector的实现类,后进先出的堆栈,线程安全
-
Set接口:HashSet:底层数据结构哈希表(数组),内部排序,元素唯一,可以有一个null,元素的存储位置根据元素的HashCode
来决定,线程不安全
LinkedHashSet:底层数据结构双向链表,维护元素的插入顺序,线程不安全
TreeSet:底层数据结构红黑树,内部排序,线程不安全
Map接口的子类:键值对的集合(双列集合)
-
HashTable:
-
HashMap:底层数据结构哈希表(数组),key不可重复,value可重复,线程不安全。
LinkedHashMap:底层数据结构哈希表和双向链表,具有可预知的迭代顺序。
WeakHashMap:WeakHashMap的键是“弱键”,相当于一种弱的HashMap
-
TreeMap:底层数据结构红黑树,有序,线程不安全。根据key值对key-value键值对进行排序,每个key-value节点作为红黑树的节点。排序方式分为两种,一种是自然排序,一种是定制排序,具体取决于其使用的构造方法
-
IdentifyHashMap:底层数据结构是数组,不一样的是比如key的索引为0,那么value保留紧跟着的位置上,而且相同索引会顺序往下排,循环时索引的自增是+2。