Java集合-Collection-List、Set、Map、队列(Queue)

在Java中,Collection接口是集合框架的根接口之一,它表示一组对象的集合。Collection接口提供了对集合进行基本操作的方法,如添加、删除、遍历等。它定义了以下常用方法:

  1. boolean add(E e):将指定的元素添加到集合中(可选操作)。
  2. boolean addAll(Collection<? extends E> c):将指定集合中的所有元素添加到集合中(可选操作)。
  3. void clear():从集合中移除所有元素(可选操作)。
  4. boolean contains(Object o):如果集合中包含指定的元素,则返回true。
  5. boolean containsAll(Collection<?> c):如果集合包含指定集合中的所有元素,则返回true。
  6. boolean isEmpty():如果集合不包含任何元素,则返回true。
  7. Iterator<E> iterator():返回在此集合上进行迭代的迭代器。
  8. boolean remove(Object o):从集合中移除指定的元素(可选操作)。
  9. boolean removeAll(Collection<?> c):从集合中移除包含在指定集合中的所有元素(可选操作)。
  10. boolean retainAll(Collection<?> c):仅保留集合中包含在指定集合中的元素(可选操作)。
  11. int size():返回集合中的元素个数。
  12. Object[] toArray():返回包含集合所有元素的数组。
  13. <T> T[] toArray(T[] a):返回包含集合所有元素的数组,并根据指定数组的运行时类型进行转换。

Collection接口的常见实现类包括ListSetQueue等,它们分别表示有序集合、无序集合和队列。通过实现Collection接口,可以使得各种集合类具有统一的操作方式和特性,从而更方便地进行集合操作和管理。

下面是 Java 中 Collection、List、Set 和 Map 之间的关系图:

                    ┌──────── Collection ────────┐
                    │                         	 │
                    │                            │
  ┌─────────────────┴─────────┐       ┌──────────┴─────────┐
  │                     │       	  │                    │
  │                     │       	  │                    │
 List                   Set 	 	Queue                Map
  │                     │       	  │                    │
  │                     │         	  │                    │
  │                     │         	  │                    │
ArrayList           HashSet   |  PriorityQueue          HashMap
LinkedList          TreeSet   │    LinkedList           TreeMap
Vector              LinkedHashSet                     LinkedHashMap
                        │
                        │
                     EnumSet
  • Collection 是所有集合类的根接口,它定义了集合类的通用行为和方法。
  • List 接口表示有序集合,允许重复元素,可以根据索引位置访问元素。
  • Set 接口表示无序集合,不允许重复元素,不支持索引访问。
  • Queue 接口表示队列,通常按照先进先出(FIFO)的方式处理元素。
  • Map 接口表示键值对的集合,其中每个键都是唯一的,键关联到值。

具体实现类如下:

  • ArrayListLinkedListVector 实现了 List 接口,分别表示动态数组、链表和向量。
  • HashSetTreeSetLinkedHashSet 实现了 Set 接口,分别表示哈希集、树集和链哈希集。
  • PriorityQueue 实现了 Queue 接口,表示优先级队列。
  • HashMapTreeMapLinkedHashMap 实现了 Map 接口,分别表示哈希映射、树映射和链哈希映射。
  • EnumSetSet 接口的特殊实现,用于存储枚举类型的元素。

这些类之间的关系是通过实现接口或继承来实现的。

EnumSet 是 Java 中用于表示枚举类型元素集合的特殊类。 它是 AbstractSet 的子类,设计用来与枚举类型一起使用,提供了高效的枚举集合实现。

特点和使用方法包括:

  1. 只能存储枚举类型的元素EnumSet 只能存储同一枚举类型的元素,不能存储其他类型的对象。
  2. 底层使用位向量实现EnumSet 使用位向量(bit vector)来表示集合中的元素,因此非常高效。
  3. 不允许存储 null 值EnumSet 不允许存储 null 值,如果尝试存储 null 值会抛出 NullPointerException
  4. 枚举元素顺序与枚举常量声明顺序一致EnumSet 中的枚举元素的迭代顺序与枚举常量声明的顺序一致。
  5. 不是线程安全的EnumSet 不是线程安全的,如果多个线程同时访问同一个 EnumSet 实例,并且至少有一个线程修改了集合,那么它必须在外部进行同步。
  6. 性能高效:由于底层使用位向量实现,因此 EnumSet 提供了非常高效的性能。

以下是一个简单的示例,演示了如何使用 EnumSet

import java.util.EnumSet;

public class EnumSetExample {
    enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY }

    public static void main(String[] args) {
        // 创建一个包含所有枚举值的 EnumSet
        EnumSet<Day> allDays = EnumSet.allOf(Day.class);
        System.out.println("All days: " + allDays);

        // 创建一个空的 EnumSet
        EnumSet<Day> emptySet = EnumSet.noneOf(Day.class);
        System.out.println("Empty set: " + emptySet);

        // 创建一个包含指定范围的 EnumSet
        EnumSet<Day> workDays = EnumSet.range(Day.MONDAY, Day.FRIDAY);
        System.out.println("Work days: " + workDays);

        // 创建一个 EnumSet,排除指定的元素
        EnumSet<Day> weekend = EnumSet.complementOf(workDays);
        System.out.println("Weekend: " + weekend);
    }
}

输出结果为:

All days: [SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY]
Empty set: []
Work days: [MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY]
Weekend: [SUNDAY, SATURDAY]

这个示例展示了如何创建和使用 EnumSet,包括使用 allOf()noneOf()range()complementOf() 方法创建不同类型的 EnumSet

List 是一个接口,它表示一个有序的集合,并且允许存储重复的元素。List 接口是 Collection 接口的子接口,它定义了一系列操作列表的方法,例如添加元素、删除元素、获取元素等。

常见的 List 实现类包括:

  1. ArrayList:基于动态数组实现的列表,支持快速随机访问元素,但在插入和删除操作时性能略低于 LinkedList
  2. LinkedList:基于双向链表实现的列表,适合频繁的插入和删除操作,但在随机访问元素时性能较差。
  3. Vector:与 ArrayList 类似,但是是线程安全的,通常不推荐使用,因为它的性能比 ArrayList 差。
  4. Stack:栈的实现类,继承自 Vector,提供了后进先出(LIFO)的操作。

以下是一些常用的 List 接口的方法:

  • boolean add(E e):将指定的元素添加到列表的尾部。
  • void add(int index, E element):将指定的元素插入到列表的指定位置。
  • E get(int index):返回列表中指定位置的元素。
  • int indexOf(Object o):返回列表中指定元素的第一个匹配项的索引,如果列表中不包含该元素,则返回 -1。
  • boolean remove(Object o):从列表中删除指定元素的第一个匹配项,如果存在。
  • int size():返回列表中的元素数量。

示例:

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

public class Main {
    public static void main(String[] args) {
        // 创建一个ArrayList实例
        List<String> list = new ArrayList<>();

        // 向列表中添加元素
        list.add("Apple");
        list.add("Banana");
        list.add("Orange");

        // 获取列表中的元素
        System.out.println("Elements in the list:");
        for (String fruit : list) {
            System.out.println(fruit);
        }
        // 在指定位置插入元素
        list.add(1, "Grapes");

        // 移除指定元素
        list.remove("Orange");

        // 获取元素的索引
        int index = list.indexOf("Banana");
        System.out.println("Index of Banana: " + index);

        // 获取列表的大小
        System.out.println("Size of the list: " + list.size());
    }
}

这段代码演示了如何使用 ArrayList 实现类来创建、添加、删除和访问列表中的元素。

Stack 类是 Java 中的栈实现,它继承自 Vector 类,并提供了一组后进先出(LIFO)的操作方法。栈通常用于实现一些需要后进先出顺序的场景,比如计算机中的函数调用栈、浏览器中的历史记录等。

Stack 类的常用方法包括:

  • void push(E item):将指定元素压入栈顶。
  • E pop():弹出栈顶元素,并将其从栈中移除。
  • E peek():获取但不移除栈顶元素。
  • boolean empty():判断栈是否为空。
  • int search(Object o):查找指定元素在栈中的位置,如果存在则返回其在栈中的距离(1 表示位于栈顶,2 表示位于栈顶下方,以此类推);如果不存在,则返回 -1。

以下是一个简单的示例,演示了如何使用 Stack 类:

import java.util.Stack;

public class Main {
    public static void main(String[] args) {
        // 创建一个栈实例
        Stack<String> stack = new Stack<>();

        // 将元素压入栈顶
        stack.push("Apple");
        stack.push("Banana");
        stack.push("Orange");

        // 弹出栈顶元素
        String top = stack.pop();
        System.out.println("Popped element: " + top);

        // 获取但不移除栈顶元素
        String peeked = stack.peek();
        System.out.println("Peeked element: " + peeked);

        // 判断栈是否为空
        boolean isEmpty = stack.empty();
        System.out.println("Is stack empty? " + isEmpty);

        // 查找元素在栈中的位置
        int index = stack.search("Banana");
        System.out.println("Index of Banana: " + index);
    }
}

在这个示例中,我们创建了一个 Stack 实例,并使用 push 方法将元素压入栈顶,然后使用 pop 方法弹出栈顶元素。我们还使用了 peek 方法获取但不移除栈顶元素,并使用 empty 方法判断栈是否为空。最后,我们使用 search 方法查找指定元素在栈中的位置。

Set 是一种集合接口,它代表了一组不包含重复元素的集合。Set 接口继承自 Collection 接口,因此它具有集合的基本操作,如添加、删除、检查元素等。

Set 接口的常见实现类包括:

  1. HashSet:基于哈希表实现,不保证元素的顺序,允许使用 null 元素。
  2. TreeSet:基于红黑树实现,可以确保元素的排序顺序。
  3. LinkedHashSet:继承自 HashSet,使用链表维护元素的插入顺序,可以保证元素的迭代顺序与插入顺序一致。

Set 接口的主要特点包括:

  • 不允许重复元素:Set 集合中的元素是唯一的,即集合中不会包含重复的元素。
  • 无序性(或者特定顺序性):Set 集合通常不保证元素的顺序,即元素在集合中的排列顺序可能是不确定的。
  • 可以包含 null 元素:Set 集合允许包含一个 null 元素,且只能包含一个。

以下是一个示例,展示了如何使用 HashSet 类来创建和操作集合:

import java.util.HashSet;
import java.util.Set;

public class Main {
    public static void main(String[] args) {
        // 创建一个 HashSet 实例
        Set<String> set = new HashSet<>();

        // 添加元素到集合中
        set.add("Apple");
        set.add("Banana");
        set.add("Orange");
        set.add("Apple"); // 添加重复元素

        // 输出集合的大小
        System.out.println("Size of set: " + set.size());

        // 遍历集合并输出元素
        System.out.println("Elements in set:");
        for (String element : set) {
            System.out.println(element);
        }

        // 检查集合是否包含指定元素
        System.out.println("Contains Banana? " + set.contains("Banana"));

        // 删除指定元素
        set.remove("Orange");

        // 清空集合
        set.clear();

        // 检查集合是否为空
        System.out.println("Is set empty? " + set.isEmpty());
    }
}

在上面的示例中,我们创建了一个 HashSet 实例,并向其中添加了几个元素。由于 HashSet 不允许包含重复元素,因此在添加重复元素时,集合的大小没有增加。然后,我们遍历集合并输出了其中的元素,使用 contains 方法检查集合是否包含指定元素,并使用 remove 方法删除了指定元素。最后,我们使用 clear 方法清空了集合,并使用 isEmpty 方法检查集合是否为空。

Map 是一种键值对的集合,它将键映射到值。 每个键都必须是唯一的,但是值可以重复。Map 接口定义了一系列方法来操作键值对集合,包括添加、删除、获取、检查键值对等操作。

Map 接口的常见实现类包括:

  1. HashMap:基于哈希表实现,不保证键值对的顺序,允许使用 null 键和 null 值。
  2. TreeMap:基于红黑树实现,可以按照键的自然顺序或者自定义顺序对键值对进行排序。
  3. LinkedHashMap:继承自 HashMap,使用双向链表维护键值对的插入顺序,可以保证遍历顺序与插入顺序一致。

Map 接口的主要特点包括:

  • 键的唯一性:Map 中的键是唯一的,即同一个键只能对应一个值。
  • 无序性(或者特定顺序性):Map 集合通常不保证键值对的顺序,即键值对在集合中的排列顺序可能是不确定的。
  • 可以包含 null 键和 null 值:Map 集合允许包含一个 null 键和多个 null 值。

以下是一个示例,展示了如何使用 HashMap 类来创建和操作映射:

import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void main(String[] args) {
        // 创建一个 HashMap 实例
        Map<String, Integer> map = new HashMap<>();

        // 添加键值对到映射中
        map.put("Apple", 10);
        map.put("Banana", 20);
        map.put("Orange", 15);
        map.put("Apple", 30); // 替换已存在的键对应的值

        // 获取指定键对应的值
        System.out.println("Value of Apple: " + map.get("Apple"));

        // 遍历映射并输出键值对
        System.out.println("Entries in map:");
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + " : " + entry.getValue());
        }
        // 检查映射是否包含指定键
        System.out.println("Contains key Banana? " + map.containsKey("Banana"));

        // 删除指定键对应的值
        map.remove("Orange");

        // 清空映射
        map.clear();

        // 检查映射是否为空
        System.out.println("Is map empty? " + map.isEmpty());
    }
}

在上面的示例中,我们创建了一个 HashMap 实例,并向其中添加了几个键值对。由于 HashMap 不允许包含重复键,因此在添加重复键时,旧的值会被新的值所替换。然后,我们使用 get 方法获取指定键对应的值,使用 entrySet 方法遍历映射并输出其中的键值对,使用 containsKey 方法检查映射是否包含指定键,使用 remove 方法删除指定键对应的值,最后使用 clear 方法清空映射,并使用 isEmpty 方法检查映射是否为空。

Set和Map: Set 用于存储一组唯一的元素,而 Map 用于存储键值对的映射关系。在选择使用时,根据需求和特定场景来确定使用 Set 还是 Map。

队列(Queue)是一种基本的数据结构,遵循先进先出(FIFO)的原则,即先进入队列的元素会先被取出。 Java 中的队列通常用于实现缓冲区、任务调度等场景。Java 提供了多种队列的实现,常见的包括 LinkedListArrayDequePriorityQueue

Queue 接口定义了一系列方法,包括:

boolean add(E e):将指定的元素插入队列,如果队列已满则抛出异常。
boolean offer(E e):将指定的元素插入队列,如果队列已满则返回 false。
E remove():移除并返回队列的头部元素,如果队列为空则抛出异常。
E poll():移除并返回队列的头部元素,如果队列为空则返回 null。
E element():返回队列的头部元素,但不移除,如果队列为空则抛出异常。
E peek():返回队列的头部元素,但不移除,如果队列为空则返回 null。
  1. LinkedList
    • LinkedList 是双向链表实现的队列,可以作为队列或双端队列使用。
    • 它支持在队列的两端进行添加、删除元素操作。
    • LinkedList 实现了 Queue 接口,因此可以直接用作队列。
Queue<Integer> queue = new LinkedList<>();
queue.offer(1); // 入队
queue.offer(2);
int front = queue.peek(); // 查看队首元素
int removedElement = queue.poll(); // 出队
  1. ArrayDeque
    • ArrayDeque 是数组实现的双端队列,也可以作为队列使用。
    • 它支持高效的在队列两端进行添加、删除元素操作,但不支持随机访问。
    • ArrayDeque 实现了 Queue 接口,因此也可以直接用作队列。
Queue<Integer> queue = new ArrayDeque<>();
queue.offer(1); // 入队
queue.offer(2);
int front = queue.peek(); // 查看队首元素
int removedElement = queue.poll(); // 出队
  1. PriorityQueue
    • PriorityQueue 是基于优先级堆实现的优先级队列。
    • 元素在插入时会根据优先级进行排序,每次出队操作会弹出优先级最高的元素。
    • PriorityQueue 实现了 Queue 接口,因此也可以直接用作队列。
Queue<Integer> queue = new PriorityQueue<>();
queue.offer(3); // 入队
queue.offer(1);
int front = queue.peek(); // 查看队首元素(最小值)
int removedElement = queue.poll(); // 出队(弹出最小值)

这些是 Java 中常用的队列实现方式,选择合适的队列取决于具体的应用场景和需求。

  • 18
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

星辰yzy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值