Java 中的集合接口详解

目录

1、Java Collection 接口详解

(1)Java集合之List接口

(2)Java集合之Set接口

(2)Java集合之Queue接口

2、Java Map接口详解

3、遍历集合的三种方式

(1)使用增强for循环(foreach循环)

(2)使用 forEach 方法和 Stream API(Java 8及以上)

(3)使用迭代器(Iterator)

4、集合中的批量操作

3、集合中的数组操作 Array Operations 


        Java的集合类主要由两个接口派生而出:Collection接口和Map接口。

        核心集合接口封装了不同类型的集合,这些接口允许独立于集合表示的细节来操作集合。核心集合接口是Java集合框架的基础。// 注意,Map和Collection是相互独立的

1、Java Collection 接口详解

        当涉及Java中的集合框架时,Collection接口是一个重要的核心接口,定义了对一组对象进行操作和管理的通用方法。下面是对Java Collection接口的详细解释:

1)概述:

  1. Collection接口是Java集合框架的根接口之一,位于java.util包中。
  2. Collection接口表示一组对象的集合,这些对象可以是任何类型,包括基本类型的包装类和用户自定义类。
  3. Collection接口是其他集合接口(如List和Set)的父接口,它提供了一组通用的方法,这些方法可以在不同类型的集合上进行操作。// 线性数据结构的通用接口(Map是键值对映射)

2)常用方法:// 对一个数据容器的增删改查操作

  1. int size():返回集合中的元素数量。
  2. boolean isEmpty():检查集合是否为空。
  3. boolean contains(Object obj):检查集合是否包含指定元素。
  4. boolean add(E element):向集合中添加一个元素。
  5. boolean remove(Object obj):从集合中移除指定元素。
  6. void clear():清空集合中的所有元素。
  7. Iterator<E> iterator():返回一个用于遍历集合的迭代器。

3)迭代器(Iterator):

  1. Collection接口提供了iterator()方法,用于获取一个实现了Iterator接口的迭代器对象。
  2. 迭代器可以用于按顺序遍历集合中的元素,通过调用hasNext()方法判断是否还有下一个元素,调用next()方法获取下一个元素。// 迭代器是一种设计模式,通过代码实现
  3. 迭代器还提供了remove()方法,用于从集合中移除当前元素。

4)数组与集合的转换:

        Collection接口提供了两个方法,可以将集合转换为数组,或者将数组转换为集合:

  1. Object[] toArray():将集合转换为一个对象数组。
  2. <T> T[] toArray(T[] array):将集合转换为指定类型的数组。

// Collection接口本来就是线性数据结构的通用接口,转为数组也很正常

5)equals() 和 hashCode():

        Collection接口继承了equals()和hashCode()方法,用于判断集合的相等性和计算集合的哈希码。

  1. equals()方法用于比较两个集合是否包含相同的元素,通常需要实现类重写该方法。
  2. hashCode()方法用于计算集合的哈希码,通常需要实现类重写该方法。

// 使用哈希码可以进行高效的查找和存储操作。需要注意的是,哈希码并不是唯一的,即不同的对象可能具有相同的哈希码(哈希冲突)

6)并发性:

  1. Collection接口不是线程安全的,如果在多线程环境下使用,需要进行额外的同步控制。
  2. Java提供了并发集合类,如ConcurrentHashMap和ConcurrentLinkedQueue,用于在多线程环境下进行安全的并发操作。

        理解Java Collection接口,可以更好地使用和管理集合对象,并了解集合框架的常用操作和特性。此外,Java提供了许多实现Collection接口的类,包括ArrayList、LinkedList、HashSet、TreeSet等,它们提供了不同的数据结构和特性,可以根据实际需求选择合适的实现类来操作和管理集合。

(1)Java集合之List接口

        List接口是Java集合框架中的一种有序、可重复的集合接口,位于java.util包中。它继承自Collection接口,并在其基础上提供了一系列操作有序元素的方法。下面是对List接口的详细解释:

1)概述://有序可重合

  1. List接口表示一个有序的集合,其中的元素可以按照插入顺序进行访问。
  2. List允许存储重复的元素,同一个元素可以出现多次。
  3. List接口继承了Collection接口,因此它包含了Collection接口中定义的大部分方法。

2)主要方法:

        添加元素:

  1. boolean add(E element): 将元素添加到列表的末尾。
  2. void add(int index, E element): 在指定位置插入元素。

        访问元素:

  1. E get(int index): 获取指定位置的元素。
  2. int indexOf(Object element): 返回指定元素第一次出现的位置。

        修改元素:

  • E set(int index, E element): 替换指定位置的元素。

        删除元素:

  1. E remove(int index): 删除指定位置的元素。
  2. boolean remove(Object element): 删除第一次出现的指定元素。

        其他方法:

  1. int size(): 返回列表的元素个数。
  2. boolean contains(Object element): 判断列表是否包含指定元素。
  3. boolean isEmpty(): 判断列表是否为空。
  4. void clear(): 清空列表中的所有元素。
  5. Iterator<E> iterator(): 返回一个迭代器,用于遍历列表中的元素。

3)常见实现类:

  1. ArrayList:基于动态数组实现,支持快速随机访问和插入/删除操作,但对于频繁的插入/删除操作性能较差。// 快速查询
  2. LinkedList:基于双向链表实现,支持快速插入/删除操作,但随机访问的性能较差。//快速修改
  3. Vector:与ArrayList类似,但是是线程安全的,通常在多线程环境中使用。
  4. Stack:继承自Vector,实现了后进先出(LIFO)的堆栈数据结构。

        需要注意的是,List接口提供了根据索引访问和操作元素的方法,因此可以根据索引来操作列表中的元素顺序。另外,List接口还实现了Iterable接口,因此可以使用增强的for循环(foreach循环)来遍历列表中的元素。

(2)Java集合之Set接口

        Set接口是Java集合框架中的一种集合类型,位于java.util包中。它表示一组不重复的元素,不保证元素的顺序。下面是对Set接口的详细解释:// 跟List对应(可重复、有序)

1)概述:

  1. Set接口表示一个无序的集合,其中的元素不重复
  2. Set不保证元素的顺序,即不维护元素的插入顺序或访问顺序。
  3. Set接口继承自Collection接口,因此它包含了Collection接口中定义的大部分方法。

2)主要方法:

        添加元素:

  1. boolean add(E element): 将元素添加到Set中。
  2. boolean addAll(Collection<? extends E> collection): 将一个集合中的元素添加到Set中。

        访问元素:

  1. boolean contains(Object element): 判断Set中是否包含指定元素。
  2. boolean containsAll(Collection<?> collection): 判断Set是否包含另一个集合中的所有元素。
  3. Iterator<E> iterator(): 返回一个迭代器,用于遍历Set中的元素。

        删除元素:

  1. boolean remove(Object element): 从Set中删除指定元素。
  2. boolean removeAll(Collection<?> collection): 删除Set中与另一个集合中相同的元素。
  3. boolean retainAll(Collection<?> collection): 保留Set中与另一个集合中相同的元素,删除其他元素。

        其他方法:

  1. int size(): 返回Set中的元素个数。
  2. boolean isEmpty(): 判断Set是否为空。
  3. void clear(): 清空Set中的所有元素。

        常见实现类:

  1. HashSet:基于哈希表实现,它通过哈希码来存储和访问元素,具有快速的插入、删除和查找操作。// 快速访问,底层是Hash表
  2. TreeSet:基于红黑树实现,它能够对元素进行排序,并提供了一些有序的集合操作。
  3. LinkedHashSet:基于哈希表和链表实现,它保留了元素的插入顺序,同时具有HashSet的快速访问特性。

         Set接口不允许存储重复的元素。当向Set中添加元素时,如果元素已经存在,则添加操作将被忽略,不会导致Set中出现重复的元素。Set接口提供了高效的元素查找和判断功能,适用于需要检查元素是否存在或需要去重的场景。根据具体的需求,选择合适的Set实现类能够满足不同的性能和排序要求。

(2)Java集合之Queue接口

        Queue接口是Java集合框架中的一种接口,位于java.util包中。它代表了一种队列(Queue)数据结构,用于存储和操作一组元素。Queue接口定义了一些常用的队列操作,例如添加元素、获取元素、删除元素等。下面是对Queue接口的详细解释:// 队列是有序的,可以用来保证排队顺序

1)概述:

  1. Queue接口代表了一种先进先出(FIFO)的数据结构,其中元素按照添加的顺序进行排列。
  2. Queue接口继承自Collection接口,因此它包含了Collection接口中定义的一些方法,以及新增的一些队列操作方法。

2)主要方法:

        添加元素:

  1. boolean add(E element): 将指定元素添加到队列中。如果队列已满,抛出异常。
  2. boolean offer(E element): 将指定元素添加到队列中。如果队列已满,返回false。

        获取元素:

  1. E element(): 获取队列的头部元素,但不删除该元素。如果队列为空,抛出异常。
  2. E peek(): 获取队列的头部元素,但不删除该元素。如果队列为空,返回null。

        删除元素:

  1. E remove(): 获取并删除队列的头部元素。如果队列为空,抛出异常。
  2. E poll(): 获取并删除队列的头部元素。如果队列为空,返回null。

        其他方法:

  1. int size(): 返回队列中的元素个数。
  2. boolean isEmpty(): 判断队列是否为空。
  3. void clear(): 清空队列中的所有元素。

        常见实现类:// Queue有很多种实现形式,底层数据结构不一样,性能也不一样

  1. LinkedList:基于双向链表实现的队列。它既可以作为List集合使用,也可以作为Queue队列使用。
  2. ArrayDeque:基于数组实现的双端队列。它既可以作为Queue队列使用,也可以作为Deque双端队列使用。
  3. PriorityQueue:基于优先级堆实现的优先级队列。它按照元素的优先级进行排序,优先级高的元素先被取出。

        Queue接口是一种有序的队列,它遵循先进先出(FIFO)的原则。元素添加到队列的末尾,从队列的头部获取和删除元素。Queue接口的实现类可以根据具体的需求进行选择,例如LinkedList常用于实现普通队列,ArrayDeque常用于实现双端队列,PriorityQueue常用于实现优先级队列等。

        该部分的详细使用请参考这篇文章《Java 数据结构之队列(Queue)详解

2、Java Map接口详解

        Map接口是Java集合框架中的一种接口,位于java.util包中。它代表了一种映射(Mapping)关系,用于存储键-值对。Map接口提供了根据键来获取值、添加键值对、删除键值对等常用操作。下面是对Map接口的详细解释:

1)概述:

  1. Map接口表示了一种键值对的映射关系,其中的键和值都可以是任意的对象。
  2. Map中的键是唯一的,每个键只能关联一个值。
  3. Map接口继承自Collection接口中的Iterable和size方法,同时定义了一些额外的操作方法。

2)主要方法:

        添加键值对:

  1. V put(K key, V value): 将指定的键和值添加到Map中。如果键已存在,将替换原有的值,并返回被替换的值。
  2. void putAll(Map<? extends K, ? extends V> map): 将另一个Map中的所有键值对添加到当前Map中。

        获取值:

  1. V get(Object key): 根据键获取对应的值。如果键不存在,则返回null。
  2. boolean containsKey(Object key): 判断Map中是否包含指定的键。
  3. boolean containsValue(Object value): 判断Map中是否包含指定的值。

        删除键值对:

  1. V remove(Object key): 根据键删除对应的键值对,并返回被删除的值。
  2. void clear(): 清空Map中的所有键值对。

        其他方法:

  1. int size(): 返回Map中键值对的个数。
  2. boolean isEmpty(): 判断Map是否为空。
  3. Set<K> keySet(): 返回包含Map中所有键的Set集合。
  4. Collection<V> values(): 返回包含Map中所有值的Collection集合。
  5. Set<Map.Entry<K, V>> entrySet(): 返回包含Map中所有键值对的Set集合。

        常见实现类:

  1. HashMap:基于哈希表实现的Map,它使用键的哈希码来存储和访问键值对,具有快速的查找和插入操作。
  2. TreeMap:基于红黑树实现的有序Map,它按照键的自然顺序或指定的比较器对键进行排序。
  3. LinkedHashMap:基于哈希表和双向链表实现的Map,它保留了键的插入顺序或访问顺序。

        Map接口提供了丰富的操作方法,可以根据键来获取、添加、删除和修改对应的值。通过Map接口,可以实现键值对的存储和检索,非常适合需要根据键快速查找对应值的场景

3、遍历集合的三种方式

        在Java中,遍历集合可以使用多种方式,具体选择哪种方式取决于集合的类型和遍历的需求。下面是常用的遍历集合的方式:

(1)使用增强for循环(foreach循环)

        增强for循环是一种简化遍历集合的语法。它可以直接遍历数组或实现了Iterable接口的集合类。示例:

List<String> list = new ArrayList<>();
// 添加元素到list中
for (String element : list) {
    // 处理元素
}

(2)使用 forEach 方法和 Stream API(Java 8及以上)

        针对Java 8及以上版本,集合类提供了forEach方法,可以传入一个Lambda表达式或方法引用来处理每个元素。示例:

List<String> list = new ArrayList<>();
// 添加元素到list中
list.forEach(element -> {
    // 处理元素
});

        Stream API提供了丰富的流操作,包括过滤、映射、排序等,也可以用于遍历集合。通过将集合转换为流,可以使用Stream API提供的各种操作来处理元素。示例:

List<String> list = new ArrayList<>();
// 添加元素到list中
list.stream().forEach(element -> {
    // 处理元素
});

(3)使用迭代器(Iterator)

        Iterator是一个对象,能够遍历集合,并根据需要有选择地从集合中删除元素。通过调用集合的Iterator方法,可以获得集合的Iterator。下面是Iterator接口。

package java.util;
import java.util.function.Consumer;
/**
 * 迭代器允许调用者在迭代期间从集合中删除元素。
 * Iterators allow the caller to remove elements from the underlying collection during the iteration with well-defined semantics.
 */
public interface Iterator<E> {
    // 如果迭代有更多的元素,返回 true
    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());
    }
}

        如果迭代有更多的元素,则hasNext方法返回true,next方法返回迭代中的下一个元素。remove方法从基础集合中删除next返回的最后一个元素。每次调用next时,只能调用remove方法一次,如果违反此规则,则会抛出异常。

        注意: Iterator.remove()是在集合遍历时修改集合的唯一安全方法

        以下情况,需要使用Iterator替换for-each构造遍历集合:

  • 遍历集合时删除集合中的元素。for-each结构隐藏了迭代器,不能调用remove。
  • 并行遍历多个集合。

        for-each构造遍历时删除元素会导致被删除元素后的元素在集合中位置前移,导致结果与预期不同

        下面的方法展示了如何使用Iterator来遍历集合,同时删除特定的元素。

static void filter(Collection<?> c) {
    for (Iterator<?> it = c.iterator(); it.hasNext(); )
        if (!cond(it.next()))
            it.remove();
}

        这段代码是多态的,这意味着无论实现如何,它都适用于任何集合。完整的例子:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        List<String> c = new ArrayList<>();
        c.add("A");
        c.add("B");
        c.add("C");
        for (Iterator<String> it = c.iterator(); it.hasNext(); ) {
            if (cond(it.next())) {
                it.remove();
            }
        }
//        Iterator<String> it = c.iterator();
//        while(it.hasNext()){ // 判断迭代中是否还有元素
//            String next = it.next(); // 返回迭代中的下一个元素
//            if (next.equals("B"))
//                it.remove();
//        }
        c.forEach(System.out::println);
    }
    // 删除条件
    public static Boolean cond(String str) {
        if (str.equals("A")) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }
}

4、集合中的批量操作

        批量操作是对整个集合执行操作。

  1. containsAll — 如果目标集合包含指定集合中的所有元素,则返回true。
  2. addAll — 将指定集合中的所有元素添加到目标集合。(并集)
  3. removeAll — 从目标集合中删除同样包含在指定集合中的所有元素。(差集)
  4. retainAll — 从目标集合中移除指定集合中不包含的所有元素。也就是说,它只保留目标集合中同时包含在指定集合中的那些元素。(交集)
  5. clear — 从集合中删除所有元素。

        比如,从Collection c中删除指定元素e的所有实例。

c.removeAll(Collections.singleton(e));

        或者希望从集合中删除所有空元素。

c.removeAll(Collections.singleton(null));

3、集合中的数组操作 Array Operations 

        提供toArray方法是为了集合能够和使用数组的旧api之间进行兼容。集合的数组操作允许将集合的内容转换为数组。

        列如,将集合内容转储到一个新分配的数组中

Object[] a = c.toArray(); // 不指定类型
String[] a = c.toArray(new String[0]); // 指定类型

        附:java集合具体实现的总结:

关于Java集合可以参考的文章:

java集合框架综述

java集合框架综述 - 平凡希 - 博客园

集合各实现类的底层实现原理_一条很老的腊肉的博客-CSDN博客

Map 综述(一):彻头彻尾理解 HashMap_书呆子Rico的博客-CSDN博客_hashmap

15道常见的 Java集合类 面试题 - 知乎

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

swadian2008

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值