持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第八天,点击查看活动详情
Java集合框架
前言
Java集合框架是将一些特设类,如Dictionary, Vector, Stack, 和 Properties 这些类用来存储和操作对象组,统一主题。
Java集合框架被设计满足以下几个目的:
- 该框架必须高性能
- 该框架允许不同类型的集合,以类似的方式工作,具有高度的相互操作性
- 对一个集合的扩展和适应必须简单
集合框架图
Java集合工具包位于Java.util包下,Java的集合主要有两个接口派生而出:
Collection和Map,这两个接口也是Java集合框架的根接口
Collection(集合):存储一个元素集合Map(图):存储键/值对映射
我们通过框架图来简单概括一下:
-
集合接口(
Iterator、Collection、Map、ListIterator、List、Set):表示不同集合类型,是集合框架的基础 -
抽象类(
AbstractMap、AbstractCollection、AbstractList、AbstractSet、AbstractSequentialList):对集合接口的部分实现。可扩展为自定义集合类 -
实现类(
HashMap、TreeMap、Vector、Stack、ArrayList、LinkedList、HashSet、TreeSet、LinkedHashMap、LinkedHashSet):对接口的具体实现
Collection和Map
Collection
Collection是一个接口,是高度抽象出的集合,它包含了集合的基本操作和属性。Collection包含了List和Set两个大分支。
-
List: 是一个有序的队列,没有个元素都有它的索引,索引从0开始。List的具体实现类:LinkedList、ArrayList、Vector、Stack -
Set: 是不允许有重复元素的集合(集合是无序的)Set的实现类:HastSet、TreeSet。HastSet是依赖于HashMap,它实际是通过HashMap来实现的。TreeSet是依赖于TreeMap,它实际是通过TreeMap来实现的
List接口
List集合代表一个有序集合,集合中每个元素都有其对应的顺序索引。List集合允许使用重复元素,可以通过索引来访问指定位置的集合元素
实现List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。
1. ArrayList
ArrayList是一个动态数组,它允许插入null,初始长度为10,该长度代表了数组的大小,每次存放都会进行容量检测,当发现容量不足时,ArrayList就会扩容
ArrayList擅长于随机访问。同时ArrayList是非同步的
2. LinkedList
LinkedList是一个双向链表。所以它除了有ArrayList的基本操作方法外还额外提供了get,remove,insert方法在LinkedList的首部或尾部。
3. Vector
与ArrayList相似,但是Vector是同步的。所以说Vector是线程安全的动态数组。它的操作与ArrayList几乎一样
4. Stack
Stack继承自Vector,实现一个后进先出的堆栈
Set
Set是一种不包括重复元素的Collection,它维持它自己的内部排序,所以随机访问没有任何意义。与List一样,它同样允许null的存在但是仅有一个。由于Set接口的特殊性,所有传入Set集合中的元素都必须不同,同时要注意任何可变对象,如果在对集合中元素进行操作时,导致e1.equals(e2)==true,则必定会产生某些问题。Set接口有三个具体实现类,分别是散列集HashSet、链式散列集LinkedHashSet和树形集TreeSet。
虽然Set中元素没有顺序,但是元素在set中的位置是由该元素的HashCode决定的,其具体位置其实是固定的
1. HashSet
HashSet 是一个没有重复元素的集合。它是由HashMap实现的,不保证元素的顺序(这里所说的没有顺序是指:元素插入的顺序与输出的顺序不一致),而且HashSet允许使用null 元素。HashSet是非同步的,如果多个线程同时访问一个哈希set,而其中至少一个线程修改了该set,那么它必须保持外部同步
HashSet按Hash算法来存储集合的元素,因此具有很好的存取和查找性能。
2. LinkedHashSet
LinkedHashSet继承自HashSet,其底层是基于LinkedHashMap来实现的,有序,非同步。LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。这样使得元素看起来像是以插入顺序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。
3. TreeSet
TreeSet是一个有序集合,其底层是基于TreeMap实现的,非线程安全。TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序和定制排序,其中自然排序为默认的排序方式。 当我们构造TreeSet时,若使用不带参数的构造函数,则TreeSet的使用自然比较器;若用户需要使用自定义的比较器,则需要使用带比较器的参数。
TreeSet集合不是通过hashcode和equals函数来比较元素的.它是通过compare或者comparaeTo函数来判断元素是否相等.compare函数通过判断两个对象的id,相同的id判断为重复元素,不会被加入到集合中
Map
Map是一个映射接口,也就是key-value键值对。Map中每个元素都是以key-value的形式,即一个key对应一个value,所以不能存放相同的key,value可以相同
1. HashMap
以哈希表数据结构实现,查找对象时通过哈希函数计算其位置,它是为快速查询而设计的,其内部定义了一个hash表数组(Entry[] table),元素会通过哈希转换函数将元素的哈希地址转换成数组中存放的索引,如果有冲突,则使用散列链表的形式将所有相同哈希地址的元素串起来,可能通过查看HashMap.Entry的源码它是一个单链表结构
2. LinkedHashMap
LinkedHashMap是HashMap的一个子类,它保留插入的顺序,如果需要输出的顺序和输入时的相同,那么就选用LinkedHashMap。
3. TreeMap
TreeMap 是一个有序的key-value集合,非同步,基于红黑树(Red-Black tree)实现,每一个key-value节点作为红黑树的一个节点。 TreeMap存储时会进行排序的,会根据key来对key-value键值对进行排序,其中排序方式也是分为两种,一种是自然排序,一种是定制排序,具体取决于使用的构造方法。
-
自然排序:
TreeMap中所有的key必须实现Comparable接口,并且所有的key都应该是同一个类的对象,否则会报ClassCastException异常 -
定制排序: 定义
TreeMap时,创建一个comparator对象,该对象对所有的treeMap中所有的key值进行排序,采用定制排序的时候不需要TreeMap中所有的key必须实现Comparable接口。
TreeMap判断两个元素相等的标准:两个key通过compareTo()方法返回0,则认为这两个key相等。
如果使用自定义的类来作为TreeMap中的key值,且想让TreeMap能够良好的工作,则必须重写自定义类中的equals()方法,TreeMap中判断相等的标准是:两个key通过equals()方法返回为true,并且通过compareTo()方法比较应该返回为0