【Java】吃透集合框架:List、Set、Queue 和 Map 的核心用法与代码实战

大家好,我是云扬~ 今天来和大家深入聊聊 Java 集合框架中最核心的四大组件:List、Set、Queue 和 Map。作为后端开发中高频使用的数据结构,它们各自有着独特的特性和适用场景,掌握好它们的用法能让我们的代码更高效、更优雅。下面结合具体特征和代码示例,带大家全面吃透这些集合类~

一、集合框架总览

Java 集合框架的核心是Collection接口和Map接口,其中Collection主要包含三大分支:

  • List:有序、可重复,支持下标操作
  • Set:无序、不可重复,无下标支持
  • Queue:遵循特定顺序(如 FIFO)的队列结构
  • Map:独立于 Collection,存储键值对(key 唯一,value 可重复)

先上一张核心接口关系图,帮大家建立整体认知:

Collection
├── List(有序可重复)
│   ├── ArrayList(数组实现)
│   ├── LinkedList(链表实现)
│   └── Vector(线程安全,低效)
├── Set(无序不可重复)
│   ├── HashSet(哈希实现,去重)
│   ├── LinkedHashSet(有序去重)
│   └── TreeSet(排序去重)
└── Queue(队列)
    ├── ArrayDeque(双端队列)
    ├── LinkedList(队列实现)
    └── PriorityQueue(优先级队列)
Map
├── HashMap(哈希实现,无序)
├── LinkedHashMap(有序键值对)
└── TreeMap(排序键值对)

二、List:有序可重复的动态数组

List 的核心优势是存取有序、支持下标操作,适合需要按顺序存储且可能重复的数据场景。

1. ArrayList(数组实现,随机存取高效)

核心特征:基于动态数组,随机访问快(O (1)),中间增删慢(需复制移动元素),非线程安全。

代码示例:ArrayList 的增删改查

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

public class ArrayListDemo {
    public static void main(String[] args) {
        // 初始化ArrayList(初始容量16,负载因子0.75)
        List<String> list = new ArrayList();
        
        // 增:尾部添加(高效)
        list.add("Java");
        list.add("MySQL");
        list.add("Java"); // 允许重复元素
        System.out.println("添加后:" + list); // 输出:[Java, MySQL, Java]
        
        // 改:通过下标修改
        list.set(1, "Redis");
        System.out.println("修改后:" + list); // 输出:[Java, Redis, Java]
        
        // 查:随机访问(高效)
        String element = list.get(0);
        System.out.println("下标0的元素:" + element); // 输出:Java
        
        // 删:中间删除(低效,需移动元素)
        list.remove(2);
        System.out.println("删除后:" + list); // 输出:[Java, Redis]
        
        // 遍历(下标遍历最高效)
        for (int i = 0; i < list.size(); i++) {
            System.out.println("遍历元素:" + list.get(i));
        }
    }
}

2. LinkedList(双向链表,增删高效)

核心特征:基于双向链表,中间增删快(O (1)),随机访问慢(O (n)),支持队列 / 栈操作。

代码示例:LinkedList 的队列用法

import java.util.LinkedList;
import java.util.Queue;

public class LinkedListDemo {
    public static void main(String[] args) {
        // 作为队列使用(FIFO)
        Queue<String> queue = new LinkedList<>();

        // 入队:offer()(推荐,失败返回false)
        queue.offer("任务1");
        queue.offer("任务2");
        queue.offer("任务3");
        System.out.println("队列内容:" + queue); // 输出:[任务1, 任务2, 任务3]

        // 出队:poll()(移除并返回头部,空队列返回null)
        String task = queue.poll();
        System.out.println("执行任务:" + task); // 输出:任务1
        System.out.println("出队后:" + queue); // 输出:[任务2, 任务3]

        // 查看头部:peek()(不删除)
        String head = queue.peek();
        System.out.println("当前头部任务:" + head); // 输出:任务2

        // 作为链表,中间插入(高效)
        List<String> linkedList = new LinkedList<>(queue);
        linkedList.add(1, "紧急任务");
        System.out.println("插入后:" + linkedList); // 输出:[任务2, 紧急任务, 任务3]
    }
}

3. 避坑提醒

  • 避免用VectorStack:Vector 是线程安全的 ArrayList,但效率极低;Stack 已被 ArrayDeque 取代。
  • 大数据量场景:如果需要频繁增删,优先用 LinkedList;需要频繁查询,优先用 ArrayList。

三、Set:无序不可重复的去重神器

Set 的核心价值是自动去重,适合存储不需要重复的数据(如用户 ID、关键词等)。

1. HashSet(基于 HashMap,去重首选)

核心特征:底层是 HashMap(值为固定 Object),无序,去重效率高,允许 null 元素。

代码示例:HashSet 去重实战

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

public class HashSetDemo {
    public static void main(String[] args) {
        // 统计文章中不重复的单词
        String article = "Java 是最好的语言 Java 语言 后端开发 最好的";
        String[] words = article.split(" ");

        Set<String> uniqueWords = new HashSet<>();
        for (String word : words) {
            uniqueWords.add(word); // 自动去重
        }

        System.out.println("不重复单词数:" + uniqueWords.size()); // 输出:5
        System.out.println("不重复单词:" + uniqueWords); // 输出:[Java, 语言, 最好的, 后端开发, 是](无序)
    }
}

2. LinkedHashSet(有序去重)

核心特征:继承 HashSet,底层是 LinkedHashMap,既保留去重特性,又能维护插入顺序。

import java.util.LinkedHashSet;
import java.util.Set;

public class LinkedHashSetDemo {
    public static void main(String[] args) {
        Set<String> set = new LinkedHashSet<>();
        set.add("张三");
        set.add("李四");
        set.add("张三"); // 去重
        set.add("王五");

        // 输出顺序与插入顺序一致
        System.out.println(set); // 输出:[张三, 李四, 王五]
    }
}

3. TreeSet(排序去重)

核心特征:底层是 TreeMap,按自然顺序或自定义比较器排序,不允许 null 元素。

import java.util.TreeSet;
import java.util.Set;

public class TreeSetDemo {
    public static void main(String[] args) {
        // 自然排序(整数升序)
        Set<Integer> numSet = new TreeSet numSet.add(3);
        numSet.add(1);
        numSet.add(2);
        numSet.add(3); // 去重
        System.out.println("自然排序:" + numSet); // 输出:[1, 2, 3]
        
        // 自定义比较器(字符串长度降序)
        Set> strSet = new TreeSet s2) -> s2.length() - s1.length());
        strSet.add("apple");
        strSet.add("banana");
        strSet.add("cherry");
        System.out.println("自定义排序:" + strSet); // 输出:[banana, cherry, apple]
    }
}

四、Queue:遵循规则的队列结构

Queue 的核心是遵循特定访问顺序,常见场景:任务队列、消息队列等。

1. ArrayDeque(双端队列,高效替代 Stack)

核心特征:基于循环数组,支持两端增删(O (1)),随机访问快,效率高于 LinkedList。

import java.util.ArrayDeque;
import java.util.Deque;

public class ArrayDequeDemo {
    public static void main(String[] args) {
        // 作为栈使用(LIFO)
        Deque<String> stack = new ArrayDeque<>();
        stack.push("页面A");
        stack.push("页面B");
        stack.push("页面C");

        System.out.println("栈顶元素:" + stack.peek()); // 输出:页面C
        String popPage = stack.pop();
        System.out.println("出栈元素:" + popPage); // 输出:页面C
        System.out.println("栈剩余:" + stack); // 输出:[页面B, 页面A]

        // 作为双端队列,两端操作
        Deque<String> deque = new ArrayDeque<>();
        deque.addFirst("头部元素");
        deque.addLast("尾部元素");
        System.out.println("双端队列:" + deque); // 输出:[头部元素, 尾部元素]
        deque.removeFirst();
        deque.removeLast();
        System.out.println("清空后:" + deque); // 输出:[]
    }
}

2. PriorityQueue(优先级队列)

核心特征:基于堆结构,出队顺序按优先级(默认升序),元素需实现 Comparable 接口。

import java.util.PriorityQueue;
import java.util.Queue;

// 自定义任务类,实现Comparable接口
class Task implements Comparable<Task> {
    private String name;
    private int priority; // 优先级:数字越大越优先

    public Task(String name, int priority) {
        this.name = name;
        this.priority = priority;
    }

    @Override
    public int compareTo(Task o) {
        // 降序排序(优先级高的先出队)
        return o.priority - this.priority;
    }

    @Override
    public String toString() {
        return name + "(优先级:" + priority + ")";
    }
}

public class PriorityQueueDemo {
    public static void main(String[] args) {
        Queue queue = new PriorityQueue();
        queue.offer(new Task("普通任务", 1));
        queue.offer(new Task("紧急任务", 3));
        queue.offer(new Task("重要任务", 2));
        
        // 按优先级出队
        while (!queue.isEmpty()) {
            System.out.println("执行任务:" + queue.poll());
        }
        // 输出顺序:紧急任务(优先级:3) → 重要任务(优先级:2) → 普通任务(优先级:1)
    }
}

五、Map:键值对的高效存储

Map 是键值对集合,核心是通过 key 快速查找 value,key 唯一且不可重复。

1. HashMap(哈希实现,日常首选)

核心特征:底层是哈希表(数组 + 链表 / 红黑树),查询效率高(O (1)),无序,key 和 value 均可为 null。

代码示例:HashMap 的常用操作

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

public class HashMapDemo {
    public static void main(String[] args) {
        Map<String, Integer> userAge = new HashMap<>();
        userAge.put("张三", 25);
        userAge.put("李四", 30);
        userAge.put("王五", 28);
        userAge.put("张三", 26); // key重复,覆盖value
        System.out.println("HashMap内容:" + userAge); // 输出:{李四=30, 张三=26, 王五=28}(无序)

        // 查:get()
        int age = userAge.get("李四");
        System.out.println("李四的年龄:" + age); // 输出:30

        // 判存:containsKey()/containsValue()
        boolean hasZhang = userAge.containsKey("张三");
        boolean hasAge30 = userAge.containsValue(30);
        System.out.println("是否包含张三:" + hasZhang); // 输出:true
        System.out.println("是否有30岁用户:" + hasAge30); // 输出:true

        // 遍历:forEach()
        System.out.println("遍历键值对:");
        userAge.forEach((key, value) -> System.out.println(key + ":" + value));

        // 删:remove()
        userAge.remove("王五");
        System.out.println("删除后:" + userAge); // 输出:{李四=30, 张三=26}
    }
}

2. LinkedHashMap(有序键值对)

核心特征:继承 HashMap,通过双向链表维护插入 / 访问顺序,适合需要保留顺序的场景(如缓存 LRU)。

import java.util.LinkedHashMap;
import java.util.Map;

public class LinkedHashMapDemo {
    public static void main(String[] args) {
        // 维护插入顺序
        Map<String, String> map = new LinkedHashMap<>();
        map.put("a", "苹果");
        map.put("b", "香蕉");
        map.put("c", "樱桃");

        // 输出顺序与插入顺序一致
        System.out.println("插入顺序:" + map); // 输出:{a=苹果, b=香蕉, c=樱桃}

        // 访问元素后,顺序不变(默认插入顺序)
        map.get("b");
        System.out.println("访问后顺序:" + map); // 输出:{a=苹果, b=香蕉, c=樱桃}

        // 构造函数设置为访问顺序(LRU缓存核心)
        Map<String,String> lruMap = new LinkedHashMap<>( 10,0.75f, true);
        lruMap.put("a", "苹果");
        lruMap.put("b", "香蕉");
        lruMap.put("c", "樱桃");
        lruMap.get("b"); // 访问b
        System.out.println("LRU访问顺序:" + lruMap); // 输出:{a=苹果, c=樱桃, b=香蕉}(最近访问的放最后)
    }
}

3. TreeMap(排序键值对)

核心特征:底层是红黑树,按 key 自然排序或自定义排序,适合需要排序的键值对场景。

import java.util.TreeMap;
import java.util.Map;

public class TreeMapDemo {
    public static void main(String[] args) {
         // 自然排序(字符串字典序)
        Map<String, Integer> treeMap = new TreeMap<>();
        treeMap.put("banana", 3);
        treeMap.put("apple", 1);
        treeMap.put("cherry", 2);

        System.out.println("自然排序:" + treeMap); // 输出:{apple=1, banana=3, cherry=2}

        // 自定义比较器(按key长度排序)
        Map<String, Integer> customTreeMap = new TreeMap<>((k1, k2) -> k1.length() - k2.length());
        customTreeMap.put("banana", 3);
        customTreeMap.put("apple", 1);
        customTreeMap.put("pear", 2);
        System.out.println("自定义排序:" + customTreeMap); // 输出:{pear=2, apple=1, banana=3}
    }
}

六、总结:集合类选择指南

场景需求推荐集合
有序可重复、频繁查询ArrayList
有序可重复、频繁增删LinkedList
去重、无序HashSet
去重、有序LinkedHashSet
去重、排序TreeSet
队列、栈操作ArrayDeque
优先级任务队列PriorityQueue
键值对、无序、高效查询HashMap
键值对、有序LinkedHashMap
键值对、排序TreeMap

以上就是 Java 集合框架核心组件的全部内容啦~ 每个集合类都有其设计初衷,掌握它们的底层实现和适用场景,才能在实际开发中做出最优选择。如果大家有疑问或补充,欢迎在评论区交流~ 下期再见!

Tags:

发表回复

Your email address will not be published. Required fields are marked *.

*
*