通用容器类
通用容器类Collection接口Collection接口源码Collection接口概述 List接口List接口源码List接口概述 Set接口Set接口源码Set接口概述 Queue接口Queue源码Queue概述 Map接口Map接口源码 总结
通用容器类
Java 提供了一组丰富的通用容器类(也称为集合框架,Collections Framework),用于存储和管理一组对象。这些容器类提供了灵活的数据结构,支持各种操作如添加、删除、遍历等,并且可以根据不同的需求选择最合适的实现。
为什么我们需要容器类呢? 从数学的角度分析,你可以使用集合的概念来理解容器。相同元素组成的,就是一个集合。在Java程序中,我们经常需要存储多个相同的对象;你可能想到,我们可以使用数组来进行存储。没错,数组确实也算是一种集合;但是数组有一些缺陷,比如,我们需要预先确定要申请的空间大小;只支持顺序查找;删除元素的时候,需要移动数组里面的其他元素。这样就导致效率比较低;或者说数组只能支持特定的一些业务场景。但是我们可能有别的场景,比如需要大量删除操作,使用数组就不方便。因为我们需要使用很多的不同种类的容器类。
Java给我们提供了一个容器类体系,让我们不需要再从头构建这些通用容器。容器类体系如下:
Collection接口
Java 的 Collection 接口是 Java 集合框架(Collections Framework)中的一个顶层接口,它定义了一组通用的操作和行为,适用于所有集合类。通过实现这个接口,各种具体的集合类可以提供一致的方法来操作它们所包含的元素。
Collection接口源码
public interface Collection<E> extends Iterable<E> { int size();// 返回集合中的元素数量 boolean isEmpty(); // 判断集合是否为空 boolean contains(Object var1);// 判断集合是否包含指定元素 Iterator<E> iterator(); // 返回一个迭代器用于遍历集合中的元素 Object[] toArray(); // 将集合转换为数组 <T> T[] toArray(T[] var1); // 将集合转换为指定类型的数组 default <T> T[] toArray(IntFunction<T[]> generator) { return this.toArray((Object[])generator.apply(0)); } boolean add(E var1); // 集合添加元素 boolean remove(Object var1); // 集合删除某个元素 boolean containsAll(Collection<?> var1); // 集合是不是包含另一个集合全部元素 boolean addAll(Collection<? extends E> var1); // 将指定集合中的所有元素添加到当前集合 boolean removeAll(Collection<?> var1); // 移除当前集合中所有与指定集合相同的元素 default boolean removeIf(Predicate<? super E> filter) { Objects.requireNonNull(filter); boolean removed = false; Iterator each = this.iterator(); while(each.hasNext()) { if (filter.test(each.next())) { each.remove(); removed = true; } } return removed; } boolean retainAll(Collection<?> var1); // 仅保留当前集合中与指定集合相同的元素,移除其他元素 void clear(); // 清空集合 boolean equals(Object var1); int hashCode(); default Spliterator<E> spliterator() { return Spliterators.spliterator(this, 0); } default Stream<E> stream() { return StreamSupport.stream(this.spliterator(), false); } default Stream<E> parallelStream() { return StreamSupport.stream(this.spliterator(), true); }}
Collection接口概述
Collection 接口概述
定义:Collection 是一个代表一组对象(称为元素)的容器的接口。它是所有集合类的顶级接口,但不包括映射(Map)。特点: 提供了基本的集合操作方法,如添加、删除、遍历等。不保证元素的顺序,也不保证元素是否唯一(这些特性由具体实现决定)。可以包含重复元素(取决于具体实现),并且允许 null 元素(同样取决于具体实现)List接口
List 接口是 Java 集合框架中的一个重要接口,继承自 Collection 接口。它代表了一个有序的集合(也称为序列),允许包含重复元素,并且可以通过索引访问这些元素。与 Set 不同的是,List 中可以存在多个相同的元素,并且保持插入顺序。
List接口源码
List接口继承Collection接口,源码我们只展示非Collection接口的方法。
public interface List<E> extends Collection<E> { // 省略掉Collection接口方法与带有默认实现的方法 E get(int var1); E set(int var1, E var2); int indexOf(Object var1); int lastIndexOf(Object var1); ListIterator<E> listIterator(); ListIterator<E> listIterator(int var1); List<E> subList(int var1, int var2);}
List接口继承Collection接口,所以这个接口拥有所有我们上面介绍的Collection接口的所有方法。List接口也扩展了一些额外方法;我简单在这里介绍一下:
索引操作 E get(int index):返回指定位置的元素。E set(int index, E element):用指定元素替换指定位置的元素,并返回旧元素。void add(int index, E element):在指定位置插入元素,后续元素会向后移动。E remove(int index):移除指定位置的元素,并返回该元素;后续元素会向前移动。 搜索操作 int indexOf(Object o):返回指定元素第一次出现的位置;如果不存在,则返回 -1。int lastIndexOf(Object o):返回指定元素最后一次出现的位置;如果不存在,则返回 -1。 子列表操作 List subList(int fromIndex, int toIndex):返回从 fromIndex(包括)到 toIndex(不包括)之间的子列表视图。对子列表的操作会影响到原始列表。List接口概述
List 接口概述
定义:List 是一个有序集合,其中每个元素都有一个对应的索引位置。你可以通过索引来访问、插入或删除元素。特点: 有序性:List 维护元素的插入顺序,即元素的迭代顺序与它们被添加到列表中的顺序相同。可重复性:允许存储重复的元素。随机访问:支持通过索引快速访问元素,这使得查找特定位置的元素非常高效。Set接口
Set 接口是 Java 集合框架中的一个重要接口,继承自 Collection 接口。它代表了一个不允许重复元素的集合,即每个元素在 Set 中都是唯一的。与 List 不同的是,Set 不保证元素的顺序(除非是某些特定实现如 LinkedHashSet 或 TreeSet)。
Set接口源码
排除掉Collection已有的方法,因为Set继承自Collection方法,我们就不展示Collection方法
public interface Set<E> extends Collection<E> {// 省略掉Collection已有的方法 和带有默认实现的方法}
我们会发现,Set接口除了多了一些带有默认实现的方法,其他方法与Collection接口方法保持一致。
Set接口概述
Set 接口概述
定义:Set 是一个不包含重复元素的集合。根据具体实现的不同,它可以维护或不维护元素的插入顺序,并且可以对元素进行排序。特点: 唯一性:确保集合中没有重复元素(基于元素的 equals() 方法和 hashCode() 方法来判断相等性)。无序性:大多数 Set 实现(如 HashSet)不保证元素的迭代顺序;但是,某些实现(如 LinkedHashSet 和 TreeSet)会保持特定的顺序。Queue接口
Queue 接口是 Java 集合框架中的一个接口,它扩展了 Collection 接口,并提供了额外的方法来插入、移除和检查元素。与 List 和 Set 不同的是,Queue 主要用于处理先进先出(FIFO, First-In-First-Out)的数据结构,但也支持其他类型的队列如优先级队列。
Queue源码
public interface Queue<E> extends Collection<E> { boolean add(E var1); boolean offer(E var1); E remove(); E poll(); E element(); E peek();}
插入操作 boolean add(E e):将指定元素插入队列的尾部;如果队列已满,则抛出 IllegalStateException。boolean offer(E e):将指定元素插入队列的尾部;如果插入失败(例如队列已满),则返回 false。 移除操作 E remove():移除并返回队列头部的元素;如果队列为空,则抛出 NoSuchElementException。E poll():移除并返回队列头部的元素;如果队列为空,则返回 null。 检查操作 E element():返回但不移除队列头部的元素;如果队列为空,则抛出 NoSuchElementException。E peek():返回但不移除队列头部的元素;如果队列为空,则返回 null。 Queue概述
Queue 接口概述
定义:Queue 是一个集合,通常用于存储将要被处理的元素,按照某种顺序(通常是 FIFO)进行处理。特点: 插入操作:一般在队列的尾部添加元素。移除操作:一般从队列的头部移除元素。检查操作:可以查看但不移除队列头部的元素。特殊实现:除了经典的 FIFO 行为外,Queue 还可以实现更复杂的队列类型,如优先级队列或双端队列(Deque)Map接口
Map 接口是 Java 集合框架中的一个重要接口,它表示键值对(key-value pairs)的集合。与 Collection 接口不同的是,Map 不存储单个元素,而是存储键和值之间的映射关系。每个键最多只能映射到一个值,并且键是唯一的(即不允许重复)。
Map接口源码
public interface Map<K, V> { 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); Set<K> keySet(); Collection<V> values(); Set<Map.Entry<K, V>> entrySet();}
基本操作 V put(K key, V value):将指定的键值对放入 Map 中。如果键已经存在,则替换旧值并返回旧值;如果键不存在,则添加新键值对并返回 null。V get(Object key):返回指定键所映射的值;如果键不存在,则返回 null。V remove(Object key):移除指定键及其对应的值,并返回被移除的值;如果键不存在,则返回 null。boolean containsKey(Object key):判断 Map 是否包含指定键。boolean containsValue(Object value):判断 Map 是否包含指定值。 批量操作 void putAll(Map<? extends K, ? extends V> m):将指定 Map 中的所有键值对复制到当前 Map 中。void clear():移除 Map 中的所有键值对。 查找操作 Set keySet():返回 Map 中所有键的集合视图。Collection values():返回 Map 中所有值的集合视图。Set<Map.Entry<K, V>> entrySet():返回 Map 中所有键值对的集合视图,其中每个元素都是一个 Map.Entry 对象,提供了对键和值的操作。 其他操作 boolean isEmpty():判断 Map 是否为空。int size():返回 Map 中键值对的数量。 总结
在 Java 中,Collection 接口表示一组数据集合,提供了基本的增、删、查和遍历等操作方法。然而,Collection 并未定义元素之间的顺序或位置,也不规定是否允许重复元素。
List 是 Collection 的一个子接口,用于表示具有顺序或位置的数据集合。它扩展了 Collection 接口,增加了根据索引位置进行操作的方法。List 有两个主要的实现类:ArrayList 和 LinkedList。ArrayList 基于数组实现,因此随机访问效率较高,但在中间插入或删除元素时需要移动其他元素,导致效率较低。相比之下,LinkedList 基于链表实现,随机访问效率较低,但插入和删除元素只需调整相邻节点的链接,效率更高。
Set 也是 Collection 的一个子接口,但它不允许包含重复元素。Set 没有增加新的方法,而是通过约束来确保集合中的唯一性。Set 的两个主要实现类是 HashSet 和 TreeSet。HashSet 基于哈希表实现,要求元素重写 hashCode 方法以提高查找效率,但不保证元素的顺序。TreeSet 基于排序二叉树实现,元素按自然顺序排列,或者在创建 TreeSet 时提供一个 Comparator 对象来自定义排序规则。此外,LinkedHashSet 是 HashSet 的一个子类,它不仅保证元素的唯一性,还按照插入顺序维护元素。另一个针对枚举类型的实现类是 EnumSet,它基于位向量实现,提供了极高的效率。
Queue 是 Collection 的一个子接口,用于表示先进先出(FIFO)的数据集合。元素可以在队列尾部添加,并从头部查看或删除。Deque 是 Queue 的一个子接口,提供了更为通用的双端队列功能,支持在头或尾部进行查看、添加和删除操作。Queue 的两个主要实现类是 LinkedList 和 ArrayDeque。LinkedList 基于双向链表实现,而 ArrayDeque 基于循环数组实现。通常情况下,如果只需要使用 Deque 接口的功能,ArrayDeque 的性能会更好一些。
Map 接口表示键值对的集合,通常根据键进行操作。Map 的两个主要实现类是 HashMap 和 TreeMap。HashMap 基于哈希表实现,要求键重写 hashCode 方法,从而提供高效的查找、插入和删除操作,但不保证元素的顺序。TreeMap 基于排序二叉树实现,要求键实现 Comparable 接口,或者在创建时提供一个 Comparator 对象,虽然操作效率略低于 HashMap,但可以按键有序排列元素。
欢迎阅读我之前的关于特定容器的文章:
LinkedList 和 ArrayDequeArrayListHashMap 和 HashSet