Java集合(一)--集合框架简析

接下来的对Java的分析都是基于jdk1.8版本

在开发过程中,常常需要集中存放多个数据。我们知道,数组可以实现这个功能。但是,数组的长度是固定的,如果我们存放的数据数量是动态变化的该怎么办?这个时候,就要用到Java的集合类了。

集合框架

所有的集合都位于java.util包下。Java集合类有两个主要的接口:Collection和Map。他们是集合的根接口。在集合中,Map结尾的类实现了Map接口,而其他的集合类实现了Collection接口。

集合框架图

图片来自:https://img-blog.csdn.net/20160124221843905

分析一下上图:

1、Collection是一个接口,它包含了集合的基本操作和属性。分为了List、Set和Queue三大分支。其中,List是一个有序的队列,其中的元素不唯一。而Set是一个无序的集合,其中的元素是唯一的。

2、List的实现类有ArrayList、LinkedList、Vector及Stack。

3、Set的实现类有HashSet、TreeSet、LinkedHashSet及EnumSet。

4、Map也是一个接口,而且是一个映射接口,值以键值对(key-value)的形式存储。实现类有EnumMap、HashMap、TreeMap、WeakHaskMap、ConcurrentHashMap及IdentityHashMap。

5、Iteator是一个用来遍历集合的工具,我们可以看到Collection接口就依赖于Iterabe接口,所以,在Collection的实现类中可以使用Iterator来遍历元素。

接下来,就一个个看一下。

Collection及其实现

Collection的定义及方法

Collection接口的定义如下:

public interface Collection<E> extends Iterable<E> {}

集合层次结构中的根接口,JDK不提供此接口的任何直接实现:它提供了更具体的子接口的实现,如Set和List。

包含的API如下:

Iterator<E> iterator();

int size();

boolean isEmpty();

Object[] toArray();

<T> T[] toArray(T[] a);

boolean add(E e);

boolean addAll(Collection<? extends E> c);

boolean remove(Object o);

boolean removeAll(Collection<?> c);

boolean contains(Object o);

boolean containsAll(Collection<?> c);

boolean retainAll(Collection<?> c);

void clear();

boolean equals(Object o);

 int hashCode();

还有默认方法

default boolean removeIf(Predicate<? super E> filter) {...}

//以下三个方法与Spliterator相关

default Spliterator<E> spliterator() {...}

default Stream<E> stream() {...}

default Stream<E> parallelStream() {...}

这些方法主要就是对元素的添加、删除、比较和对集合的判空、遍历获取大小等。

List接口的定义及其方法

List接口的定义如下:

public interface List<E> extends Collection<E> {}

List是一个有序集合。该接口的用户可以精确控制列表中每个元素的插入位置。用户可以通过整数索引(列表中的位置)访问元素并搜索列表中的元素。

因为继承于Collection接口,所以包含有其定义的所有方法,并且新增了部分方法,新增的方法如下:

E get(int index);

E set(int index, E element);

void add(int index, E element);

boolean addAll(int index, Collection<? extends E> c);

E remove(int index);

int indexOf(Object o);

int lastIndexOf(Object o);

ListIterator<E> listIterator();

ListIterator<E> listIterator(int index);

List<E> subList(int fromIndex, int toIndex);

及默认方法

default void replaceAll(UnaryOperator<E> operator) {...}

default void sort(Comparator<? super E> c) {...}

//重写Collection的默认方法,主要是变了第二个参数。

@Override

    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, Spliterator.ORDERED);
    }

因为List是有序的,可以根据角标对其中的元素进行操作。所以,List中增加了部分使用角标操作数据的方法。

Set接口的定义及其方法

Set也是继承于Collection的一个接口,我们看一下它的定义:

public interface Set<E> extends Collection<E> {}

Set是一个不包含重复元素的集合。 集合中任意两个元素 e1.equals(e2)必为false。并且最多只包含一个null元素。

和List一样,Set也含有Collection定义的所有方法,但是没有新增方法,只重写了一个默认方法:

//也是只改变了第二个参数

 @Override
    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, Spliterator.DISTINCT);
    }

AbstractCollection的定义及作用

定义如下:

public abstract class AbstractCollection<E> implements Collection<E> {}

AbstractCollection是一个抽象类,实现了Collection中除了iterator()和size()之外的函数。它实现了Collection中其他集合类通用的方法,那么其他集合类(比如:AbstractList、AbstractSet及ArrayDeque)就可以通过继承它来减少部分工作。

AbstractList的定义及作用

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {}

AbstractList是一个抽象类,实现了List中除了size()和get(int Location)之外的函数。它是为了方便随机访问数据的集合(比如:AbstractSequentialList、ArrayList等)实现List。

AbstractSequentialList的定义及作用

public abstract class AbstractSequentialList<E> extends AbstractList<E> {}

继承于AbstractList,实现了其get(int index)等方法。为了方便顺序访问数据的集合(如LinkedList)实现List。

AbstractSet的定义及其作用

定义如下:

public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> {}

AbstractSet是一个抽象类,实现了equals(Object c)、hashCode()和removeAll(Collection<?> c)()方法。它是为了方便其他的类实现Set。

Queue的定义及方法

定义如下:

public interface Queue<E> extends Collection<E> {}

队列,用于在处理前保持元素的集合。 除了有基本的集合操作外,队列还提供插入,提取和检查操作。它的方法有:

//如果可以在不违反容量限制的情况下立即执行此操作,则将指定的元素插入此队列,成功时返回true,如果当前没有空间,则抛出IllegalStateException
boolean add(E e);

//如果可以在不违反容量限制的情况下立即执行此操作,则将指定的元素插入此队列。 使用容量限制队列时,此方法通常优于add(),只能通过抛出异常来插入元素。
boolean offer(E e);

//检索并删除此队列的头部。 此方法与poll()的不同之处仅在于,如果此队列为空,则会抛出异常。
E remove();

//检索并删除此队列的头部,如果此队列为空,则返回null。
E poll();

//检索但不删除此队列的头部。 此方法与 peek()的区别仅在于,如果此队列为空,则抛出异常。
E element();

//检索但不移除此队列的头部,如果此队列为空,则返回null。
E peek();

Deque的定义及方法

定义如下:

public interface Deque<E> extends Queue<E> {}

Deque是一种线性集合,支持两端插入和移除元素。此接口支持限制容量大小的队列以及不限制容量大小的队列。除了Queue的方法外,还有以下方法

//容量允许的情况下,在队列的开头插入元素。如果没有空间,则抛出IllegalStateException异常。
void addFirst(E e);

//将指定元素插入此双端队列的前面,除非它违反容量限制。 使用容量限制的双端队列时,此方法通常优于addFirst()方法
boolean offerFirst(E e);

//容量允许的情况下,在队列的末尾插入元素。如果没有空间,则抛出IllegalStateException异常。
void addLast(E e);

//在此双端队列的末尾插入指定的元素,除非它违反容量限制。 使用容量限制的双端队列时,此方法通常优于addLast()方法
boolean offerLast(E e);

//检索并删除此双端队列的第一个元素。如果此双端队列为空,则会抛出异常。
E removeFirst();

//检索并删除此双端队列的第一个元素,如果此双端队列为空,则返回null。
E pollFirst();

//检索并删除此双端队列的最后一个元素。 如果此双端队列为空,则会抛出异常。
E removeLast();

//检索并删除此双端队列的最后一个元素,如果此双端队列为空,则返回null。
E pollLast();

//检索此双端队列的第一个元素。如果队列为空,则抛出异常
E getFirst();

//检索此双端队列的第一个元素,如果此双端队列为空,则返回null。
E peekFirst();

//检索此双端队列的最后一个元素。如果队列为空,则抛出异常
E getLast();

//检索此双端队列的最后一个元素,如果此双端队列为空,则返回null。
E peekLast();

//从此双端队列中删除指定元素的第一个匹配项。如果双端队列不包含该元素,则不会更改。 如果有,删除第一个与o相同的元素,并返回true。
boolean removeFirstOccurrence(Object o);

//从此双端队列中删除指定元素的最后一个匹配项。如果双端队列不包含该元素,则不会更改。 如果有,删除最后一个与o相同的元素,并返回true。
boolean removeLastOccurrence(Object o);

//如果可以在不违反容量限制的情况下立即执行此操作,则将指定的元素插入此双端队列的尾部,成功时返回true,如果当前没有空间可用,抛出IllegalStateException异常。
boolean add(E e);

//如果可以在不违反容量限制的情况下立即执行此操作,则将指定的元素插入此双端队列的尾部,成功时返回true,如果当前没有空间可用,返回false。
boolean offer(E e);

//检索并删除此双端队列的头部。如果此双端队列为空,则会抛出异常。
E remove();

//检索并删除此双端队列的头部。如果此双端队列为空,则返回null
E poll();

//检索此双端队列的头部。如果此双端队列为空,则会抛出异常。
E element();

//检索此双端队列的头部。如果此双端队列为空,则返回null。
E peek();

//如果可以在不违反容量限制的情况下立即执行此操作,则将元素推送到此双端队列的头部,如果当前没有可用空间则抛出IllegalStateException异常。
void push(E e);

//删除并返回此双端队列的第一个元素。
E pop();

//从此双端队列中删除第一次出现的指定元素。 如果队列不包含该元素,则它将保持不变。如果有,删除第一次出现的指定元素并返回true。
boolean remove(Object o);

//如果此双端队列包含指定的元素,则返回true
boolean contains(Object o);

//反回队列中的元素个数
 int size();

//返回队列的迭代器,元素从头部到尾部顺序返回
Iterator<E> iterator();

//以相反的顺序返回此双端队列中元素的迭代器,元素从尾部到头部顺序返回
Iterator<E> descendingIterator();

Iterator及其实现

Iterator的方法及作用

Iterator是一个泛型接口,包含4个方法:

public interface Iterator<E>{

E next();

boolean hasNext();

void remove();

default void forEachRemaining(Consumer <? super E> action);

}

通过反复调用next方法,可以逐个访问集合中的每个元素。但是,到达集合末尾,next将抛出一个NoSuchElementException。因此,需要在调用next之前调用hasNext方法来判断是否有下一个元素。

在Java SE 8中可以调用forEachRemaining方法,并提供一个lambda表达式来遍历集合。

元素被访问的顺序取决于集合的类型。如果对ArrayList进行迭代,迭代器将从索引0开始,每迭代一次,索引值加一。然而,如果访问HashSet,每个元素将按照某种随机的次序出现,我们无法预知元素被访问的次序。

Java的迭代器是位于两个元素之间的,当调用next时,迭代器就越过下一个元素,并返回那个元素的引用。

Iterator接口的remove方法将会删除刚刚越过的元素。而且,不能连续调用remove方法,应该在remove方法中间使用next方法,让其越过元素。

ListIterator的方法及作用

定义如下:

public interface ListIterator<E> extends Iterator<E> {}

它继承于Iterator,用来遍历List,允许程序员在任一方向遍历列表,在迭代期间修改列表,并获取迭代器在列表中的当前位置。它没有当前元素,光标总是位于以遍历过的元素和下一个元素之间。除了Iterator的方法外,他还有自己的方法。

//反向遍历列表的时候,如果有元素,则返回true(光标前面是否有元素)
boolean hasPrevious();

/**返回列表中的上一个元素并向后移动光标位置。 可以重复调用此方法以向后遍历列表,或者与对next()的调用混合以来回传递。 (请注意,对next()和previous()的交替调用将重复返回相同的元素。
**/
E previous();

//返回后续调用next()将返回的元素的索引,如果列表迭代器位于列表的末尾,则返回列表大小。
int nextIndex();

//返回后续调用previous()将返回的元素的索引。(如果列表迭代器位于列表的开头,则返 回-1。)
int previousIndex();

//用指定的元素替换next()或previous()返回的最后一个元素(可选操作)。 只有在最后一次调用 next()或previous()后才调用remove()和add(),才能进行此调用。
void set(E e);

//将指定的元素插入列表(可选操作)。 该元素紧接在link #next()返回的元素之前插入(如果有),并且在previous()返回的元素之后插入,如果有的话。 (如果列表中不包含任何元素,则新元素将成为列表中的唯一元素。)新元素将插入隐式游标之前:next()的后续调用不受影响,随后调用previous()将返回新元素。
void add(E e);

Map及其实现

Map的定义及方法

定义如下:

public interface Map<K, V> {}

Map是一个键值对映射接口。Map中不能包含重复的键,每个键也只能映射一个值。

Map的方法:

int size();

boolean isEmpty();

boolean containsKey(Object key);

boolean containsValue(Object value);

V get(Object key);

V put(K key, V value);

V remove(Object key);

void putAll(Map<? extends K, ? extends V> m);

void clear();

Set<K> keySet();

Collection<V> values();

Set<Map.Entry<K, V>> entrySet();

boolean equals(Object o);

int hashCode();

以及默认方法

default V getOrDefault(Object key, V defaultValue){}

default void forEach(BiConsumer<? super K, ? super V> action){}

default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function){}

default V putIfAbsent(K key, V value){}

default boolean remove(Object key, Object value){}

default boolean replace(K key, V oldValue, V newValue){}

default V replace(K key, V value){}

default V computeIfAbsent(K key,
            Function<? super K, ? extends V> mappingFunction){}

default V computeIfPresent(K key,
            BiFunction<? super K, ? super V, ? extends V> remappingFunction){}

default V compute(K key,
            BiFunction<? super K, ? super V, ? extends V> remappingFunction){}

default V merge(K key, V value,
            BiFunction<? super V, ? super V, ? extends V> remappingFunction){}

Map的方法用来返回键集、值集以及键跟值的映射关系。且提供了判空、清除及删除等操作。

Map.Entry的定义及方法

定义如下:

interface Entry<K, V> {}

这是Map内部的一个接口,辅助Map的部分方法。Entry的方法有:

K getKey();

V getValue();

V setValue(V value);

boolean equals(Object o);

int hashCode();

还有部分默认方法

public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K, V>> comparingByKey(){}

public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K, V>> comparingByValue(){}

public static <K, V> Comparator<Map.Entry<K, V>> comparingByKey(Comparator<? super K> cmp){}

public static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp){}

AbstractMap定义及方法

定义如下:

public abstract class AbstractMap<K,V> implements Map<K,V> {}

此类实现了Map除entrySet()外的所有方法。内部有一个抽象类SimpleEntry继承了Entry做辅助工作。此类还有自己的方法:

//返回一个克隆副本,但是值跟键都是null
protected Object clone() throws CloneNotSupportedException {}

//SimpleEntry和SimpleImmutableEntry的实用方法。 测试是否相等,检查空值。
private static boolean eq(Object o1, Object o2) {}

ConcurrentMap的定义与方法

定义如下:

public interface ConcurrentMap<K,V> extends Map<K,V> {}

它的实现类可以为线程提供安全性和原子性保证。其实就是线程安全。它的方法如下:

V putIfAbsent(K key, V value);

boolean remove(Object key, Object value);

boolean replace(K key, V oldValue, V newValue);

V replace(K key, V value);

还有默认方法

default V getOrDefault(Object key, V defaultValue){}

default void forEach(BiConsumer<? super K, ? super V> action){}

default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function){}

default V computeIfAbsent(K key,
            Function<? super K, ? extends V> mappingFunction){}

default V computeIfPresent(K key,
            BiFunction<? super K, ? super V, ? extends V> remappingFunction){}

default V compute(K key,
                      BiFunction<? super K, ? super V, ? extends V> remappingFunction){}

default V merge(K key, V value,
            BiFunction<? super V, ? super V, ? extends V> remappingFunction){}

ConcurrentMap提供线程安全性和原子性保证的映射。

内存一致性效果:与其他并发集合一样,在将对象作为键或值放入ConcurrentMap之前的线程中的操作发生在从另一个线程中的ConcurrentMap访问或删除该对象之后的操作之前。

SortedMap定义及方法

定义如下:

public interface SortedMap<K,V> extends Map<K,V> {}

SortedMap接口主要提供有序的Map实现。它按照自然顺序或指定的比较器对键进行排序,它的实现类是TreeMap。它的方法如下:

Comparator<? super K> comparator();

SortedMap<K,V> subMap(K fromKey, K toKey);

SortedMap<K,V> headMap(K toKey);

SortedMap<K,V> tailMap(K fromKey);

K firstKey();

K lastKey();

Set<K> keySet();

Collection<V> values();

Set<Map.Entry<K, V>> entrySet();

NavigableMap的定义及方法

定义如下:

public interface NavigableMap<K,V> extends SortedMap<K,V> {}

NavigableMap扩展了 SortedMap,具有了针对给定搜索目标返回最接近匹配项的导航方法。方法 lowerEntry、floorEntry、ceilingEntry 和 higherEntry 分别返回与小于、小于等于、大于等于、大于给定键的键关联的 Map.Entry 对象,如果不存在这样的键,则返回 null。类似地,方法 lowerKey、floorKey、ceilingKey 和 higherKey 只返回关联的键。所有这些方法是为查找条目而不是遍历条目而设计的。它的方法如下:

Map.Entry<K,V> lowerEntry(K key);
 
K lowerKey(K key);
 
Map.Entry<K,V> floorEntry(K key);
 
K floorKey(K key);
 
Map.Entry<K,V> ceilingEntry(K key);
 
Map.Entry<K,V> ceilingEntry(K key);
 
K higherKey(K key);

Map.Entry<K,V> firstEntry();

Map.Entry<K,V> lastEntry();

Map.Entry<K,V> pollFirstEntry();

Map.Entry<K,V> pollLastEntry();

NavigableMap<K,V> descendingMap();

NavigableSet<K> navigableKeySet();

NavigableSet<K> descendingKeySet();

NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,K toKey,   boolean toInclusive);
 
NavigableMap<K,V> headMap(K toKey, boolean inclusive);
                             
NavigableMap<K,V> tailMap(K fromKey, boolean inclusive);
 
SortedMap<K,V> subMap(K fromKey, K toKey); 

SortedMap<K,V> headMap(K toKey);

SortedMap<K,V> tailMap(K fromKey);                             

Dictionary的定义及方法

定义如下:

public abstract class Dictionary<K,V> {}

是任何类的抽象父类,例如Hashtable,它将键映射到值。 每个键和每个值都是一个对象。 在任何一个Dictionary 对象中,每个键最多与一个值相关联。 给定Dictionary 和一个键,可以查找关联的元素。 任何非null对象都可以用作键和值。通常,此类的实现应使用equals方法来确定两个键是否相同。

它的方法有:

//返回字典中元素的个数
abstract public int size();

//当且仅当此字典不包含任何条目时,结果为true。
abstract public boolean isEmpty();

//返回此字典中的所有键
abstract public Enumeration<K> keys();

//返回此字典中的所有值
abstract public Enumeration<V> elements();

//返回键在此字典中映射到的值。
abstract public V get(Object key);

//将指定的键映射到此字典中指定的值。键和值都不能是null
abstract public V put(K key, V value);

//从此字典中删除键值对
abstract public V remove(Object key);

好了,本文就分析到这。本文的主旨是了解集合框架中比较重要的接口和类,并对它们所含的方法留有印象。在本文中没有注释的方法的作用,会在之后的其他文章中有所体现。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335