Java 集合框架【1】顶级接口

437 阅读4分钟

Java 的集合框架是 Java 基础之一,本文从顶级接口开始,了解常用的 Map 和 Collection 相关的知识。

java_collections_overview.png

这是一张比较完整的集合框架关系图,可以看见,顶级接口包括 MapCollectionDictionary 三种。

Dictionary:已标记为过时,建议使用 Map 替代,它的实现 Hashtable 也被标记为,无需线程安全用 HashMap 替代;需要线程安全,用 ConcurrentMap 替代。

所以,我们常见的需要了解的顶级集合接口主要就是 MapCollection

Collection

集合结构中的 Root Interface , 集合表示一组对象,称其为元素。有的集合允许重复元素,而有的则不允许;有的集合是有序的,而有的是无序的。JDK 中,并没有提供此接口的任何实现,它有三个子接口 SetQueueList 。 它继承自 Iterable

// 实现此接口允许对象成为“for-each 循环”语句的目标。 请参阅 For-each 循环
public interface Iterable<T> {
	// 迭代器
	Iterator<T> iterator();
	// 默认 foreach 
	default void forEach(Consumer<? super T> action) {
    	Objects.requireNonNull(action);
    	for (T t : this) {
        	action.accept(t);
    	}
	}
	// 分离器
	default Spliterator<T> spliterator() {
    	return Spliterators.spliteratorUnknownSize(iterator(), 0);
	}
}
  • Iterator : 集合上的迭代器。 迭代器在 Java 集合框架中取代了枚举。 迭代器在两个方面不同于枚举:
    • 迭代器允许调用者在具有明确定义的语义逻辑的迭代期间,从底层集合中删除元素。
    • 方法名称的改进。 从它定义的方法可以分析:
public interface Iterator<E> {
	  // 用于迭代
    boolean hasNext();
    E next();
	  // 用于删除元素
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }
    // 用于对当前迭代的后续元素执行操作
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}
  • Spliterator ,可拆分迭代器,和 Iterator ⼀样,Spliterator 也⽤于遍历元素,但它是为了并⾏执⾏⽽设计的。可以将集合拆分成多个部分。这个比较复杂,后续详细讲解。

Collection 除了继承自 Iterable , 它定义了一些方法:

public interface Collection<E> extends Iterable<E> {
    
    int size();
    boolean isEmpty();
    boolean contains(Object o);
    Iterator<E> iterator();
    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);
    default boolean removeIf(Predicate<? super E> filter)
    boolean containsAll(Collection<?> c);
    boolean retainAll(Collection<?> c);
    void clear();
    boolean equals(Object o);
    int hashCode();
    default Stream<E> stream() 
    default Stream<E> parallelStream()
}

主要包括以下行为:

  • 集合元素读取相关:包括 size 、 isEmpty 和 是否包含某个元素等。
  • 添加操作:add / addAll
  • 删除操作:remove / removeAll / removeIf / clear
  • 哈希相关: equals 和 hashCode
  • 迭代器、并发迭代器相关内容
  • 数组转换能力:toArray
  • Stream 的支持

它有三个子接口,分别定义了集合框架中常用的三种数据结构:List 、 Set 和 Queue 。

  • List : 增加了批量修改、位置访问、搜索和 List 迭代的能力。
  • Set :没有增加任何新的能力,不包含重复元素的集合。更明确地说,集合不包含一对元素 e1e2 使得 e1.equals(e2),并且最多包含一个空元素。正如它的名字所暗示的,这个接口模拟了数学集合抽象。
  • Queue :这是一个用来处理之前保存的元素而设计的集合。除了基本的 Collection 操作之外,队列还提供了额外的插入、提取和检查操作。 这些方法中的每一种都以两种形式存在:一种在操作失败时抛出异常,另一种返回一个特殊值(null 或 false,取决于操作)。 后一种形式的插入操作是专门为与容量受限的队列实现一起使用而设计的; 在大多数实现中,插入操作不会失败。

Map

Map 不继承自任何接口,以 Key - Value 的保存数据,不包含重复的 Key ,且 Key 和 Value 的映射关系是 1 : 1 的。 这个接口代替了 Dictionary 类,Dictionary 是一个抽象类,而不是一个接口。 Map 提供了三个集合:Key 的集合、Value 的集合 、Key 和 Value 映射的集合。 Map 是否有顺序保证是根据不同的子类自己实现的。

在 Map 中,定义了几类能力:

  • 查询操作
  • 修改操作
  • 内部的数据结构
  • 比较和 Hash
  • 默认实现的一些方法
public interface Map<K,V> {
    // Query Operations
    int size();
    boolean isEmpty();
    boolean containsKey(Object key);
    boolean containsValue(Object value);
    V get(Object key);

    // Modification Operations
    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();

    interface Entry<K,V> {
        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) 
    }

    // 比较和 Hash
    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 的无序 Map
  • 子接口 SortedMap 的实现,有序的 Map 。

总结

关于 Root Interface 就到这里了,基本上这些 Root Interface 主要的作用就是定义通用的行为,并提供一些默认的方法实现。从顶层接口也可以分析出它们的不同之处。