美文网首页
Java集合(一)--集合框架简析

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

作者: swz_android | 来源:发表于2018-12-26 22:34 被阅读0次

    接下来的对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);
    
    

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

    相关文章

      网友评论

          本文标题:Java集合(一)--集合框架简析

          本文链接:https://www.haomeiwen.com/subject/uptllqtx.html