Java集合框架总结

《Java编程思想》集合框架简化图:

 

Java平台提供了一个全新的集合框架。“集合框架”主要由一组用来操作对象的接口组成。不同接口描述一组不同数据类型。

  • 集合接口:6个接口(短虚线表示),表示不同集合类型,是集合框架的基础。
  • 抽象类:5个抽象类(长虚线表示),对集合接口的部分实现。可扩展为自定义集合类。
  • 实现类:8个实现类(实线表示),对接口的具体实现。

 《Java编程思想》集合框架框架完整图:

 


  • Collection 接口是一组允许重复的对象。
  • Se接口继承Collection,但不允许重复,使用自己内部的一个排列机制。
  • List接口继承自Collection,允许重复,以元素安插的次序来放置元素,不会重新排列。
  • Map接口是一组成对的键-值对象,即所持有的是Key-value pairs。Map中不能有重复的Key。拥有自己的内部排列机制。
  • 容器中的元素类型都为Object。从容器中取得元素时,必须把它转换成原来的类型。

 

集合接口

一、Collection接口

1.单元素操作

  • boolean add(Object e) : 将对象添加给集合
  • boolean remove()

2.查询操作

  • int size():返回当前集合中元素的数量
  • boolean isEmpty():判断集合中是否有任何元素
  • boolean contains( Object e):查找集合中是否含有对象e
  • Iterator iterator():返回一个迭代器,用来访问集合中的各个元素

3.多元素操作

  • boolean containsAll(Collection c) : 查找集合中是否含有集合c中所有元素
  • boolean addAll( Collection c) : 将集合c中所有元素添加给该集合
  • void clear() : 删除集合中所有元素
  • void removeAll( Collection c) : 从集合中删除集合c中的所有元素
  • void retainAll( Collection c) : 从集合中删除集合c中不包含的元素

4.转换为数组操作

  • Object [] toArray():返回一个内含集合所有元素的数组
  • Object [] toArray(object [] array):返回一个内含集合所有元素的数组,返回的数组和参数array的类型相同。

注意:

  • 可以把集合转换成其它任何其它的对象数组,但是不能直接把集合转换成基本数据类型的数组,这是因为集合必须持有对象。
  • Collection不支持get()方法,如果要遍历Collection中的元素,就必须使用 Iterator 接口。
  • AbstractCollection抽象类实现了集合的一些基本功能。虽然可以自己实现Collection接口的所有方法,但是除了 iterator()和size()方法在恰当的子类中实现以外,其它所有方法都由AbstractCollection类来提供实现。

 

Iterate接口

Collection接口的 iterator()方法返回一个Iterator。 Iterator接口方法能通过迭代访问集合中各个元素,并从 Collection中删除相应的元素。

 

  1. boolean hasNext() : 判断是否存在另一个可访问的元素
  2. Object next() : 返回要访问的下一个元素。如果到达集合结尾,则抛出NoSuchElementException异常。
  3. void remove() : 删除上次访问的对象,本方法必须紧跟在上次访问(next())后执行,如果上次访问后集合已被修改,方法将抛出IlegalStateException。

 

二、List接口

Lis接口继承了 Collection接口以定义一个允许重复项的有序集合,该接口不但能够对列表的一部分进行处理,还添加了针对元素位置的操作。

 

  • void add( int index, Object e) : 在指定位置 index上添加元素 e。
  • boolean addAll( int index, Collection c) : 将集合c的所有元素添加到指定位置 index
  • Object get( int index) : 返回List中指定位置的元素。
  • int indexOf( Object e) : 返回第一个出现元素e的位置,否则返回-1。
  • int lastIndexof( Object e) : 返回最后一个出现元素e的位置,否则返回-1。
  • Object remove( (int index) : 删除指定位置上的元素。
  • Object set( int index, Object e) : 用元素e取代位置 index上的元素,并且返回旧的元素
  • ListIterator listIterator() : 返回一个列表迭代器,用来访问列表中的元素。
  • ListIterator listIterator( int index) : 返回一个列表迭代器,用来从指定位置index开始访问列表中的元素。
  • List subList(int from, int to):返回从指定位置 from到 to范围中各个元素的子列表视图,对子列表的更改,如add()、 remove()和set()调用,对父List也有影响。

 

ListIterator接口

ListIterator接口继承自Iterator接口,它用来支持添加或更改父集合中的元素,同时它还支持双向访问。ListIterator没有当前位置,光标位于调用 previous()和next()方法返回的值之间。

  • void add( Object e) : 将对象e添加到当前位置的前面。
  • void set( Object e) : 用对象e替代next()或previous()方法访问的上一个元素,如果上次调用后列表结构被修改了,那么将抛出llegalStateEXception异常。
  • boolean hasPrevious() : 判断向后迭代时是否有元素可访问。
  • Object previous() : 返回上一个对象。
  • int nextIndex() : 返回下次调用next()方法时将返回元素的索引。
  • int previousIndex() : 返回下次调用 previous方法时将返回的元素的索引。

注意:

添加新元素会导致新元素立刻被添加到内部光标的前一个位置。所以添加元素后调用 previous()方法会返回新元素,但是调用next()却不起作用,它将返回添加操作之前的下一个元素。

 

AbstractList和 AbstractSequentialList抽象类

List接口有两个抽象的实现类: AbstractList和AbstractSequentialList。

它们覆盖了 equals()和 hashCode()方法以确保两个相等的集合返回相同的哈希码,若两个列表大小相等且包含顺序相同的相同元素,则这两个列表相等。这里的 hashCode()实现在List接口定义中声明,在这两个抽象类中实现。

除了 equals()和 hashCode(),AbstractList和AbstractSequentialList实现了其余List方法的一部分。因为数据的随机访问和顺序访问是分别实现的,这使得具体列表实现的创建变得简单。我们需要定义的方法取决于自己希望支持的行为并且我们永远不必亲自提供的是 iterator方法的实现。

 

 LinkedList类和 ArrayList类

ArrayList和LinkedList是两个常用的List实现类,使用哪一种取决于特定的需要。如果要支持随机访问,并且不必在除尾部的任何位置插入或删除元素,那么使用ArrayList是很好的选择。但如果您要频繁的从列表的中间位置添加和删除元素,而且只需要顺序的访问列表元素,那么,LinkedList实现更好。

ArrayList类封装了一个 Object[] 数组,它是动态可再分配的。它有一个 capacity,这个capacity表示存储列表中元素的数组的容量。当元素添加到 ArrayList时,它的 capacity会自动增加,因此在向一个 ArrayList对象添加大量元素时,可使用 ensureCapacity()方法增加 capacity,减少重分配的次数。

这里仅给出LinkedList的类图介绍,因为ArrayList相对于之前List接口类图来讲基本一致。

注意:

 ArrayList和 LinkedList都实现 Cloneable接口,它们都提供了两个构造函数,一个无参的,一个接受另一个 Collection。

 

  • void addFirst( Object e) : 将对象e添加到列表的开头。
  • void addLast(Object e) : 将对象e添加到列表的结尾。
  • Object getFirst() : 返回列表开头的元素。
  • Object getLast() : 返回列表结尾的元素
  • Object removeFirst() : 删除并且返回列表开头的元素。
  • Object removeLast() : 删除并且返回列表结尾的元素。
  • LinkedList() : 构建一个空的链接列表。
  • LinkedList( Collection c) : 构建一个链接列表,并且添加集合c的所有元素。

 

 RandomAccess接口

标签接口,用来检测某个集合是否支持随机访问。

 

三、Set接口

Set接口继承 Collection接口,而且它不允许集合中存在重复元素,每个具体的Set实现类通过添加的对象的 equals()方法来检查唯一性。Set接口没有创建新方法,所以Set就是一个 Collection,但是其行为不同。

 

 

Hash表

Hash表是一种数据结构,用来查找对象。Hash表为每个对象计算出一个整数,称为HashCode(哈希码)。

Hash表是个链接式列表的阵列。每个列表称为一个 buckets(哈希表元)。

对象位置的计算:

index = HashCode % buckets( HashCode为对象哈希码值, buckets为哈希表元总数-简称”桶数“)

当你添加元素时,有时会遇到已经填充了元素的哈希表元,这就发生了哈希冲突。这时,必须判断该元素是否已经存在于该哈希表中。如果哈希码是合理地随机分布的,并且”桶数“足够大,那么哈希冲突的数量就会减少。另外也可以通过设定一个初始的”桶数“来更好地控制哈希表的运行。

初始”桶数“为:

 buckets = size*150 % + 1(size为预期元素的数量)

如果哈希表中的元素超过了加载因子规定的值,就必须进行再哈希,使”桶数“增倍并将原有的对象重新导入新的”桶“中。但是”桶“被删除。Java中加载因子默认值为0.75,默认”桶数“为101,当然我们可以对其进行设置。

 

SortedSet接口

SortedSet继承自Set接口,它可以维护元素的有序顺序,SortedSet接口为子集和它的两端提供了访问方法。添加到SortedSet实现类的元素必须实现Comparable接口,否则必须给它的构造函数提供一个 Comparator接口的实现。TreeSet类是它的唯一一份实现。因为Set必须包含唯一的项,如果添加元素时比较两个元素导致了返回值为0(通过 Comparable的 compareTo()方法或 Comparator的 compare()方法,那么新元素就没有添加进去。

 

  • Comparator comparator() : 返回对元素进行排序时使用的比较器,如果使用 Comparable接口的 compareTo()方法对元素进行比较,则返回null。
  • Object first() : 返回有序集合中第一个元素
  • Object last() : 返回有序集合中最后一个元素
  • SortedSet subSet(Object from,Object to) : 返回从 from至to范围内(包含左边界)元素的SortedSet子集
  • SortedSet headSet(object to) : 返回 SortedSet的一个子集
  • SortedSet tailSet(object from) : 返回 SortedSet的一个子集

 

 AbstractSet抽象类

AbstractSet类覆盖了Object类的equals()和hashCode()方法(事实上我们在重写equals()方法时也需要重写hashCode()方法)。以确保两个相等的Set返回相同的哈希码。若两个集大小相等且包含相同元素,则这两个集相等。按定义Set的哈希码是Set中元素哈希码的总和。因此不论Set的内部顺序如何,两个相等的Set会有相同的哈希码。

  • boolean equals( Object e) : 对两个对象进行比较,检验它们是否相同。
  • int hashCode() : 返回此对象的哈希码值,equals()方法比较相同的对象必须返回相同的哈希码值。

 

HashSet类类和TreeSet类

HashSet和TreeSet接口是Set接口两种常用实现。我们使用 HashSet存储重复自由的集合。如果想更加高效,我们自己实现添加到HashSet的对象的hashCode()方法。

大多数类都覆盖了 Object中缺省的hashCode()和 equals()实现,但创建自己要添加进HashSet里的类时,一定要记得覆盖hashCode()和equals()方法。TreeSet类可以从集合中以有序的方式插入和取出元素,但是添加到 TreeSet的元素必须是可排序的。

为优化 HashSet空间的使用,可以调优初始容量(initialCapacity)和负载因子(loadfactor),TreeSet不包含调优选项,因为树总是平衡的。

 HashSet类:

  • HashSet() : 创建建一个HashSet。
  • HashSet( Collection c) : 创建一个HashSet并且添加集合C中所有元素。
  • HashSet( int initialCapacity) : 创建一个拥有指定容量的HashSet。
  • HashSet(int initialCapacity, float loadfactor) :创建一个拥有指定容量和加载因子(0.0-1.0)的HashSet。

TreeSet类:

  • TreeSet() : 创建一个TreeSet。
  • TreeSet( Collection c) : 创建一个TreeSet,并且添加集合c中所有元素。
  • TreeSet( comparator c) : 创建一个TreeSet,并且使用指定的比较器对其元素进行排序。

 

LinkedHashSet(链接式哈希集)类

LinkedHashSet继承自HashSet。

如果想查看添加给 HashSet的元素的顺序,就可以使用LinkedHashSet。LinkedHashSet的迭代器按照元素的插入顺序来访问各个元素。它提供了一个可以快速访问各个元素的有序集合。同时,它也增加了实现的代价,因为哈希表元中的各个元素是通过双重链接式列表链接在一起的。

LinkedHashSet类:

  • LinkedHashSet() : 创建一个LinkedHashSet。
  • LinkedHashSet( Collection c) : 创建一个LinkedHashSet,并且添加集合c中所有元素。
  • LinkedHashSet ( int initialCapacity) : 创建个拥有指定容量的LinkedHashSet。
  • LinkedHashSet (int initialCapacity, float loadFactor) : 创建一个拥有指定容量和加载因子的LinkedHashSet。

 

 四、Map接口

Map接口不是Collection接口的子接口。Map接口用于维护键值对,该接口描述了从不重复的键到值的映射。

 

  • Object put( Object key, Object value): 将关联的一个关键字和一个值放入该映像。如果该关键字已经存在,那么与此关键字相关的新值将取代旧值。方法返回关键字的旧值,如果关键字原先并不存在,则返回null。
  • Object remove( Object key) : 从映像中删除与key相关的映射。
  • void putAll(Map m) : 将来自特定映像的所有元素添加给该映像。
  • void clear() : 从映像中删除所有映射。
  • Object get( Object key) : 获得与关键字key相关的值,并且返回与关键字key相关的对象,如果没有在该映像中找到该关键字,则返回null。
  • boolean containsKey(object key) : 判断映像中是否存在关键字key
  • boolean containsValue ( Object value) : 判断映像中是否存在值 value。
  • int size() : 返回当前映像中映射的数量。
  • boolean isEmpty() : 判断映像中是否有映射
  • Set keySet() : 返回映像中所有关键字的视图集
  • Collection values() : 返回映像中所有值的视图集
  • Set entrySet() : 返回 Map.Entry(条目)对象的视图集,即映像中的键值对

注意:

  1. keySet():因为映射中键的集合必须是唯一的,所以使用Set。还可以从视图中删除元素,同时关键字和它相关的值将从源映像中被删除,但是不能添加任何元素。
  2. values():因为映射中值的集合不是唯一的,所以使用Collection。还可以从视图中删除元素,同时值和它的关键字将从源映像中被删除,但是不能添加任何元素。
  3. entrySet():因为映射是唯一的,所以使用Set。还可以从视图中删除元素,同时这些元素将从源映像中被删除,但是不能添加任何元素。
 

 Map.Entry()接口

Map的entrySet方法返回一个实现 Map.Entry接口的对象集合。集合中每个对象都是源Map中个特定的键值对。

 

可以通过这个集合的迭代器获得每一个条目(Entry)的键或值并对值进行更改。当条目通过迭代返回后,除非是迭代器自身的remove()方法或者迭代器返回的条目中的setValue()方法,其余对源Map外部的修改都会导致此条目集变得无效,同时产生的条目行为未定义。

Object getKey() : 返回条目的关键字。

Object getValue() : 返回条目的值。

Object setvalue( Object value) : 将相关映像中的值改为value,并且返回旧值。

 

SortedMap接口

Java提供了一个特殊的Map接口SortedMap,它与SortedSet一样使集合保持一种有序序列。不过它是通过比较键来进行排序。

 

SortedMap接口为映像的视图,包括两个端点提供了访问方法。其中排序是作用于映射的键,处理 SortedMap和处理SortedSet一样。添加到 SortedMap实现类的元素必须实现Comparable接口,否则就必须给它的构造函数提供一个Comparator接口的实现, TreeMap类是SortedMap接口的唯一一份实现。

  • Comparator comparator() : 返回对关键字进行排序时使用的比较器,如果使用的是 Comparable接口的 compareTo方法对关键字进行比较,则返回null
  • Object firstKey() : 返回映像中第一个关键字。
  • Object lastKey() : 返回映像中最后一个关键字。
  • SortedMap subMap(Object from,Object to) : 返回从 from至 to范围(左包含)内元素的SortedMap视图
  • SortedMap headMap( Object toKey):返回SortedMap的一个视图
  • SortedMap tailMap( Object fromKey):返回SortedMap的一个视图

 

AbstractMap抽象类

AbstractMap类覆盖了equals()和hashCodeo()方法以确保两个相等映像返回相同的哈希码值。

如果两个映像大小相等、包含同样的键且每个键在这两个映像中对应的值都相同,则这两个映像相等。映像的哈希码是映像元素哈希码值的总和,每个元素是 Map.Entry接口的实现。不管映像内部如何排序,两个相等映像会产生相同的哈希码值。

 

HashMap类和TreeMap类

在Map中插入、删除和定位元素,HashMap是最好的选择。但如果需要按照顺序遍历键,那么 TreeMap会更好。使用 HashMap要求添加的键类明确定义了hashCode()和equals()的实现。

HashMap类:

  • HashMap() : 创建一个HashMap。
  • HashMap(Map m) : 创建一个HashMap,并且添加映像m的所有映射。
  • HashMap( int initialCapacity) : 创建一个拥有指定容量的HashMap。
  • HashMap(int initialCapacity, float loadFactor) : 创建一个拥有指定容量和加载因子的HashMap。

TreeMap类:

  • TreeMap() : 创建一个TreeMap。
  • TreeMap(Map m) : 创建一个TreeMap,并且添加映像m中所有元素。
  • TreeMap( Comparator c ) : 创建一个TreeMap,并且使用特定的比较器对关键字进行排序。
  • TreeMap( SortedMap s) : 创建一个TreeMap,添加有序映像s中所有映射,使用与有序映像s相同的比较器排序。

 

 LinkedHashMap(链接式哈希映像)类

LinkedHashMap扩展 HashMap,以插入顺序将键值对添加进LinkedHashMap中。与LinkedHashSet一样,LinkedHashMap内部也采用了双重链接式列表。

LinkedHashMap类:

  • LinkedHashMap():创建一个LinkedHashMap。
  • LinkedHashMap(Map m):创建一个LinkedHashMap,并且添加映像m中所有映射。
  • LinkedHashMap( (int initialCapacity):创建一个拥有指定容量的LinkedHashMap。
  • LinkedHashMap(int initialCapacity, float loadFactor):创建一个拥有指定容量和加载因子的LinkedHashMap
  • LinkedHashMap(int initialCapacity, float loadFactor,boolean accessOrder):创建一个拥有指定容量、加载因子和访问顺序排序的LinkedHashMap
  • boolean removeEldestEntry( Map.Entry old) : 如果想删除最老的映射可以重新定义本方法,以便有选择地在最老的映射符合某个条件或者映像超过了某个大小时返回true。

注意:

如果将 accessOrder设置为true,那么LinkedHashMap将使用访问顺序而不是插入顺序来迭代各个映像。每次调用get或者put方法时,相关的映像便从它的当前位置上删除,然后放到LinkedHashMap的结尾处(只有LinkedHashMap中的位置才会受到影响,哈希表元则不受影响,哈希表映射总是待在对应于关键字的哈希码的哈希表元中)。

 

WeakHashMap(弱哈希映像)类

WeakHashMap是Map的一个特殊实现,它使用弱引用来存放哈希表关键字。使用这种方式时,当映射的键在WeakHashMap的外部不再被引用时,垃圾收集器会将它回收,但它将把到达该对象的弱引用纳入一个队列。WeakHashMapl的运行将定期检查该队列,以便找出新到达的弱引用。当一个弱引用到达该队列时就表示关键字不再被任何人使用,并且它已经被收集起来,WeakHashMap就会删除相关的映射。

WeakHashMap类:

  • WeakHashMap() : 创建一个WeakHashMap。
  • WeakHash Map(Map m) : 创建一个WeakHashMap并且添加映像m中所有映射。
  • WeakHash Map( int initial Capacity) : 创建个拥有指定容量的WeakHashMap。
  • WeakHashMap (int initialCapacity, float loadFactor) : 创建一个拥有指定容量和加载因子的WeakHashMap。

 

 IdentityHashMap(全同哈希映像)类

IdentityHashMap也是Map的一个特殊实现。在这个类中,关键字的哈希码不是hashCode()方法来计算的,而是通过System.identityHashCode()方法进行计算(即便可能已经重新定义了 hashCode()方法)。这是Object.hashCode()根据对象的内存地址来计算哈希码时使用的方法。为了对各个对象进行比较IdentityHashMap将使用 ==,而不使用 equals()方法。这时不同的关键字对象,即使它们的内容相同,也被视为不同的对象。

IdentityHashMap类:

  • IdentityHashMap():创建一个IdentityHashMap
  • IdentityHashMap(Map m):创建一个IdentityHashMap,并且添加映像m中所有映射。
  • IdentityHashMap(int expectedMaxSize) : 创建一个拥有预期最大尺寸的空的IdentityHashMap。
posted @ 2018-12-16 19:42  问月晚安  阅读(302)  评论(0编辑  收藏  举报