java集合类有哪些?

在 Java 中,集合类(Collection classes)是指用来存储、操作数据对象的一系列类。它们位于 java.util 包中,主要分为 ListSetMap 三个类型,每个类型又包含不同的实现类。

1. List 接口及其实现类

List 是一个有序的集合,它允许元素重复,并且元素的插入顺序是被保留的。常用的 List 实现类有:

ArrayList (基于动态数组实现)

  • 底层结构ArrayList 使用一个 动态数组 来存储元素。
  • 访问:通过数组的索引进行快速访问,时间复杂度为 O(1)。
  • 插入:如果插入点在数组的末尾,则插入是常数时间 O(1),但如果在中间插入,则需要移动后续元素,时间复杂度为 O(n)。
  • 扩展 :当数组容量不足时,ArrayList 会将其容量扩展为原来的 1.5 倍。扩展的过程是 O(n)。
  • 删除:删除元素时,需要将其后的所有元素左移,时间复杂度为 O(n)。
LinkedList(基于双向链表实现)
  • 底层结构LinkedList 使用 双向链表 来存储元素,每个节点包含数据和指向前后节点的指针。
  • 访问:访问元素需要遍历链表,时间复杂度为 O(n)(从头或尾开始遍历)。
  • 插入/删除:插入和删除操作在链表的两端(头或尾)是 O(1),在中间插入或删除时需要遍历链表,时间复杂度为 O(n)。
Vector(基于动态数组实现)
  • 底层结构VectorArrayList 类似,也使用动态数组来存储数据。
  • 访问/插入 :访问和插入的时间复杂度与 ArrayList 相同。
  • 线程安全Vector 是线程安全的,通常通过 同步 来保证线程安全,这会导致一些性能开销。
Stack (基于 Vector 实现)
  • 底层结构StackVector 的一个子类,采用 动态数组 存储元素。
  • 操作push()pop() 操作是基于栈的后进先出(LIFO)特性,实际上是通过数组的 addremove 操作来实现的。
  • 线程安全 :与 Vector 类似,Stack 也是线程安全的。
java 复制代码
import java.util.*;

public class ListExample {
    public static void main(String[] args) {
        // 创建一个ArrayList
        List<String> list = new ArrayList<>();
        
        // 添加元素
        list.add("Java");
        list.add("Python");
        list.add("JavaScript");
        
        // 访问元素
        System.out.println("List: " + list);
        
        // 访问指定位置的元素
        System.out.println("Element at index 1: " + list.get(1));
        
        // 删除元素
        list.remove(1);
        System.out.println("After removal: " + list);
    }
}

2. Set 接口及其实现类

Set 是一个不允许元素重复的集合,它不保证元素的插入顺序。常用的 Set 实现类有:

HashSet(基于哈希表实现)
  • 底层结构HashSet 使用 哈希表(HashMap) 来存储元素。内部使用一个 HashMap 来存储集合元素,键是元素,值是一个常量对象(如 Boolean.TRUE)。
  • 访问:通过元素的哈希值确定其存储位置,查找元素的时间复杂度为 O(1)。
  • 插入/删除:插入和删除元素时,通过计算哈希值定位元素的位置,平均时间复杂度为 O(1),但在哈希冲突严重时,性能会下降到 O(n)。
  • 无序性HashSet 不保证元素的插入顺序。
LinkedHashSet(基于哈希表和链表实现)
  • 底层结构LinkedHashSet 使用 哈希表双向链表 结合的方式实现。哈希表提供快速的查找和插入,链表用于维护元素的插入顺序。
  • 访问 :查找元素的时间复杂度为 O(1)(与 HashSet 类似),但额外维护了一个链表,用于记录元素插入的顺序。
  • 插入/删除:插入和删除元素的时间复杂度为 O(1),但需要额外维护链表的顺序。
TreeSet(基于红黑树实现)
  • 底层结构TreeSet 使用 红黑树 来存储元素,保证元素的排序。
  • 访问:查找、插入和删除操作的时间复杂度为 O(log n),因为红黑树是自平衡的二叉搜索树。
  • 排序TreeSet 会按照元素的自然顺序(如果元素实现了 Comparable 接口)或提供的 Comparator 进行排序。
java 复制代码
import java.util.*;

public class SetExample {
    public static void main(String[] args) {
        // 创建一个HashSet
        Set<String> set = new HashSet<>();
        
        // 添加元素
        set.add("Java");
        set.add("Python");
        set.add("JavaScript");
        set.add("Java"); // 重复元素不会添加
        
        // 打印集合
        System.out.println("Set: " + set);
        
        // 使用 LinkedHashSet 来保证插入顺序
        Set<String> linkedSet = new LinkedHashSet<>();
        linkedSet.add("Java");
        linkedSet.add("Python");
        linkedSet.add("JavaScript");
        System.out.println("LinkedHashSet: " + linkedSet);
    }
}

3. Map 接口及其实现类

Map 是一个键值对集合,它允许通过键(key)来映射到值(value)。常用的 Map 实现类有:

HashMap(基于哈希表实现)
  • 底层结构HashMap 使用 哈希表 来存储键值对。哈希表是一个包含键和值的数组,键通过哈希函数映射到数组的某个位置。
  • 查找:通过键的哈希值来快速定位值,平均时间复杂度为 O(1)。
  • 冲突处理 :当多个键的哈希值相同(发生哈希冲突)时,HashMap 会将冲突的元素链式存储在同一个位置,时间复杂度退化为 O(n)。
  • 扩展 :当哈希表的负载因子超过某个阈值时,HashMap 会进行扩展,通常扩展为原来的两倍,扩展过程是 O(n)。
LinkedHashMap(基于哈希表和链表实现)
  • 底层结构LinkedHashMap 使用 哈希表双向链表 结合的方式实现。哈希表用于存储键值对,链表用于维护元素的插入顺序。
  • 查找 :查找操作的时间复杂度为 O(1),与 HashMap 类似。
  • 排序 :链表的存在使得 LinkedHashMap 能保持元素插入的顺序或者访问顺序(取决于构造时的参数)。
TreeMap(基于红黑树实现)
  • 底层结构TreeMap 使用 红黑树 来存储键值对,保证键的排序。
  • 查找:查找、插入和删除操作的时间复杂度为 O(log n),因为红黑树是自平衡的二叉搜索树。
  • 排序TreeMap 会按照键的自然顺序(如果键实现了 Comparable 接口)或提供的 Comparator 进行排序。
Hashtable(基于哈希表实现)
  • 底层结构HashtableHashMap 类似,底层也是一个 哈希表
  • 线程安全Hashtable 是线程安全的,使用同步(synchronized)来保证线程安全,因此性能较低。由于这一点,Hashtable 在现代 Java 编程中已较少使用,通常建议使用 ConcurrentHashMap
java 复制代码
import java.util.*;

public class MapExample {
    public static void main(String[] args) {
        // 创建一个HashMap
        Map<String, Integer> map = new HashMap<>();
        
        // 添加键值对
        map.put("Java", 8);
        map.put("Python", 6);
        map.put("JavaScript", 7);
        
        // 访问键值对
        System.out.println("Map: " + map);
        
        // 根据键访问值
        System.out.println("Java's value: " + map.get("Java"));
        
        // 遍历键值对
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }
}

4. Queue 接口及其实现类

Queue 是一个先进先出(FIFO)的集合接口。常用的 Queue 实现类有:

LinkedList(基于双向链表实现)
  • 底层结构LinkedList 使用 双向链表 来存储元素。它实现了 Queue 接口,可以用作队列。
  • 操作:在队列的两端进行插入和删除操作的时间复杂度为 O(1),这是链表的优势。
  • 迭代:访问队列中的元素需要遍历链表,时间复杂度为 O(n)。
PriorityQueue(基于堆实现)
  • 底层结构PriorityQueue 使用 (通常是最小堆)来存储元素。
  • 操作:插入和删除的时间复杂度为 O(log n),因为堆在插入和删除操作时需要重新调整堆的结构。
  • 排序PriorityQueue 会根据元素的自然顺序或提供的 Comparator 来确定优先级。
ArrayDeque(基于动态数组实现)
  • 底层结构ArrayDeque 使用 动态数组 来实现双端队列。它提供比 LinkedList 更高效的性能,尤其是在需要频繁访问队列两端时。
  • 操作:插入和删除操作在队列的两端都是 O(1),但是如果数组需要扩展时,扩展过程的时间复杂度为 O(n)。
java 复制代码
import java.util.*;

public class QueueExample {
    public static void main(String[] args) {
        Queue<String> queue = new LinkedList<>();
        
        // 添加元素
        queue.offer("Java");
        queue.offer("Python");
        queue.offer("JavaScript");
        
        // 移除元素
        System.out.println("Poll: " + queue.poll());  // 移除并返回队列头部元素
        System.out.println("Queue after poll: " + queue);
        
        // 查看队列头部元素
        System.out.println("Peek: " + queue.peek());  // 查看队列头部元素但不移除
    }
}

5. Deque 接口及其实现类

Deque 是双端队列(Double Ended Queue),允许在队列的两端插入和删除元素。常用的 Deque 实现类有:

ArrayDeque(基于动态数组实现)
  • 底层结构ArrayDeque 使用 动态数组 来存储元素。
  • 操作:插入和删除操作的时间复杂度是 O(1),但如果数组需要扩展,则会有 O(n) 的开销。
  • 优点 :相较于 LinkedListArrayDeque 的性能更高,因为它不需要维护链表的节点指针。
LinkedList(基于双向链表实现)
  • 底层结构LinkedList 使用 双向链表 来存储元素。
  • 操作:从两端插入和删除元素的时间复杂度为 O(1),但在中间插入或删除时,时间复杂度为 O(n)。
java 复制代码
import java.util.*;

public class DequeExample {
    public static void main(String[] args) {
        Deque<String> deque = new ArrayDeque<>();
        
        // 从两端添加元素
        deque.addFirst("Java");
        deque.addLast("Python");
        
        // 从两端移除元素
        System.out.println("Removed from front: " + deque.removeFirst());
        System.out.println("Removed from back: " + deque.removeLast());
    }
}

6. Stack 类

StackVector 的子类,表示后进先出(LIFO)数据结构,常用于实现栈操作。

java 复制代码
import java.util.*;

public class StackExample {
    public static void main(String[] args) {
        Stack<String> stack = new Stack<>();
        
        // 压栈
        stack.push("Java");
        stack.push("Python");
        stack.push("JavaScript");
        
        // 弹栈
        System.out.println("Popped: " + stack.pop());
        System.out.println("Stack after pop: " + stack);
        
        // 查看栈顶元素
        System.out.println("Peek: " + stack.peek());
    }
}

图源:代码随想录知识星球

相关推荐
zhangfeng113335 分钟前
selenium已经登陆了 我怎么查看 网页 在fRequest xhr 的数据呢
开发语言·python
ggdpzhk3 小时前
idea 编辑竖列:alt +shift+insert
java·ide·intellij-idea
hikktn3 小时前
Java 兼容读取WPS和Office图片,结合EasyExcel读取单元格信息
java·开发语言·wps
迪迦不喝可乐3 小时前
软考 高级 架构师 第十一章 面向对象分析 设计模式
java·设计模式
檀越剑指大厂4 小时前
【Java基础】使用Apache POI和Spring Boot实现Excel文件上传和解析功能
java·spring boot·apache
苹果酱05674 小时前
Golang的网络流量分配策略
java·spring boot·毕业设计·layui·课程设计
小青柑-4 小时前
Go语言中的接收器(Receiver)详解
开发语言·后端·golang
豪宇刘4 小时前
JavaScript 延迟加载的方法
开发语言·javascript
孑么4 小时前
GDPU Android移动应用 重点习题集
android·xml·java·okhttp·kotlin·android studio·webview
摇光935 小时前
js迭代器模式
开发语言·javascript·迭代器模式