Java三大最常用集合List、Set、Map用法详解

 更新时间:2026年02月25日 11:00:28   作者:苏涵.  
在Java集合框架中,List、Set、Map是最核心的三大接口,它们分别对应线性表、集合、键值对映射三种数据结构,各自有独特的设计目标和适用场景,这篇文章主要介绍了Java三大最常用集合List、Set、Map用法的相关资料,需要的朋友可以参考下

前言

List、Set、Map 作为最基础也最常用的三种集合类型,各自有着鲜明的特性和适用场景。本文梳理清楚它们的区别、用法和最佳实践,在开发中选对集合、少走弯路。

一、集合的本质

Java 集合框架的核心目的是存储、管理和操作一组对象,相比数组,集合支持动态扩容、提供丰富的操作方法(增删改查、排序、筛选等),是处理批量数据的首选。

List、Set 属于集合接口的子接口,而 Map 是独立的顶级接口(存储键值对),三者的核心差异体现在元素是否有序、是否允许重复上:

集合类型核心特征是否允许重复元素是否有序核心实现类
List有序可重复插入有序(索引有序)ArrayList、LinkedList
Set无序不可重复无序(HashSet)/ 有序(TreeSet)HashSet、TreeSet、LinkedHashSet
Map键值对存储,键唯一值可重复、键不可无序(HashMap)/ 有序(TreeMap)HashMap、TreeMap、LinkedHashMap

二、特性 + 用法 + 场景

1. List:有序可重复的 “动态数组”

List 的核心是有序性(按插入顺序保存,可通过索引访问)和可重复性(允许元素重复),就像我们日常用的 “待办清单”,可以按顺序查看、修改指定位置的内容。

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

public class ListDemo {
    public static void main(String[] args) {
        // 推荐使用接口声明,实现类实例化(面向接口编程)
        List<String> fruitList = new ArrayList<>();
        
        // 1. 添加元素
        fruitList.add("苹果");
        fruitList.add("香蕉");
        fruitList.add("苹果"); // 允许重复添加
        
        // 2. 按索引访问元素
        System.out.println("索引1的元素:" + fruitList.get(1)); // 输出:香蕉
        
        // 3. 修改元素
        fruitList.set(0, "红苹果");
        
        // 4. 遍历元素
        for (String fruit : fruitList) {
            System.out.println(fruit); // 输出:红苹果、香蕉、苹果
        }
        
        // 5. 删除元素
        fruitList.remove(2); // 删除索引2的“苹果”
    }
}

常用实现类对比:

  • ArrayList:底层是动态数组,查询快(随机访问)、增删慢(需移动元素),适合读多写少的场景;
  • LinkedList:底层是双向链表,查询慢(需遍历)、增删快(仅修改节点引用),适合写多读少(如队列、栈)的场景。

适用场景:

需要按顺序存取数据、允许重复元素、需通过索引快速访问的场景(如:订单列表、用户留言列表)。

2. Set:无序不可重复的 “无重复集合”

Set 的核心是不可重复性(元素唯一),默认无序(HashSet),就像我们的 “用户标签库”,不允许同一个标签重复出现。

核心用法示例:

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

public class SetDemo {
    public static void main(String[] args) {
        Set<String> tagSet = new HashSet<>();
        
        // 1. 添加元素
        tagSet.add("Java");
        tagSet.add("Spring");
        tagSet.add("Java"); // 重复元素,添加失败
        
        // 2. 遍历元素(无序)
        for (String tag : tagSet) {
            System.out.println(tag); // 输出:Java、Spring(顺序不固定)
        }
        
        // 3. 判断元素是否存在
        boolean hasJava = tagSet.contains("Java");
        System.out.println("是否包含Java标签:" + hasJava); // 输出:true
        
        // 4. 去重场景(核心价值)
        List<String> rawList = List.of("a", "b", "a", "c");
        Set<String> uniqueSet = new HashSet<>(rawList);
        System.out.println("去重后的集合:" + uniqueSet); // 输出:[a, b, c]
    }
}

常用实现类对比:

  • HashSet:底层基于 HashMap 实现,无序、查询快,依赖元素的hashCode()equals()保证唯一性;
  • LinkedHashSet:继承 HashSet,底层维护链表,保证插入顺序,兼具有序和去重;
  • TreeSet:底层基于红黑树,可对元素自然排序(或自定义排序),但性能略低于 HashSet。

适用场景:

需要去重、无需按顺序存取数据的场景(如:用户标签、抽奖名单(避免重复中奖)、缓存的唯一键集合)。

3. Map:键值对存储的 “字典”

Map 的核心是键值对(Key-Value) 存储,键(Key)唯一、值(Value)可重复,就像我们的 “字典”—— 通过唯一的 “单词(Key)” 找到对应的 “释义(Value)”。

核心用法示例:

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

public class MapDemo {
    public static void main(String[] args) {
        Map<Integer, String> userMap = new HashMap<>();
        
        // 1. 添加键值对
        userMap.put(1, "张三");
        userMap.put(2, "李四");
        userMap.put(1, "张小三"); // 键重复,覆盖原有值
        
        // 2. 通过键获取值
        String userName = userMap.get(2);
        System.out.println("ID为2的用户:" + userName); // 输出:李四
        
        // 3. 遍历Map(三种方式)
        // 方式1:遍历所有键
        Set<Integer> keys = userMap.keySet();
        for (Integer key : keys) {
            System.out.println("键:" + key + ",值:" + userMap.get(key));
        }
        
        // 方式2:遍历所有键值对(推荐,效率高)
        for (Map.Entry<Integer, String> entry : userMap.entrySet()) {
            System.out.println("ID:" + entry.getKey() + ",姓名:" + entry.getValue());
        }
        
        // 方式3:遍历所有值(不关心键时)
        for (String value : userMap.values()) {
            System.out.println("姓名:" + value);
        }
        
        // 4. 判断键是否存在
        boolean hasKey1 = userMap.containsKey(1);
        System.out.println("是否包含键1:" + hasKey1); // 输出:true
    }
}

常用实现类对比:

  • HashMap:底层是哈希表 + 红黑树(JDK1.8+),无序、查询 / 增删快,线程不安全,是日常开发首选;
  • LinkedHashMap:继承 HashMap,维护插入顺序,有序且高效;
  • TreeMap:基于红黑树,可按键排序,适合需要排序的键值对场景;
  • Hashtable:线程安全但性能差,已被 ConcurrentHashMap 替代,不推荐使用。

适用场景:

需要通过唯一标识(键)快速查找对应数据的场景(如:用户 ID 映射用户信息、配置项存储、缓存数据)。

三、使用集合的核心注意事项

  • Set/Map 的去重依赖hashCode()和equals():如果存储自定义对象,必须重写这两个方法,否则无法保证唯一性;
// 自定义User类示例(重写hashCode和equals)
class User {
    private Integer id;
    private String name;
    
    // 构造器、getter/setter省略
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return id.equals(user.id); // 按ID判断相等
    }
    
    @Override
    public int hashCode() {
        return id.hashCode(); // 基于ID生成哈希值
    }
}
  • 集合遍历中修改元素要注意:直接遍历 List 时用remove()会抛出ConcurrentModificationException,推荐使用迭代器或removeIf()
  • 线程安全问题:ArrayList、HashSet、HashMap 都是线程不安全的,多线程场景需使用CopyOnWriteArrayListConcurrentHashMap等线程安全集合;
  • 选择合适的实现类:优先根据 “查询 / 增删效率”“是否有序”“是否线程安全” 选择,而非无脑用 ArrayList/HashMap。

总结 

到此这篇关于Java三大最常用集合List、Set、Map用法的文章就介绍到这了,更多相关Java集合List、Set、Map内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解SpringBoot禁用Swagger的三种方式

    详解SpringBoot禁用Swagger的三种方式

    在生产环境下,我们需要关闭swagger配置,避免暴露接口的这种危险行为。本文就详细的介绍了3种情况,感兴趣的可以了解一下
    2021-11-11
  • spring boot 的常用注解使用小结

    spring boot 的常用注解使用小结

    这篇文章主要介绍了spring boot 的常用注解使用小结,需要的朋友可以参考下
    2017-05-05
  • Java打印斐波那契前N项的实现示例

    Java打印斐波那契前N项的实现示例

    这篇文章主要介绍了Java打印斐波那契前N项的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • Java中 synchronized 和 volatile的核心区别解析

    Java中 synchronized 和 volatile的核心区别解析

    本文给大家介绍Java中synchronized和volatile的核心区别,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2025-09-09
  • java调用process线程阻塞问题的解决

    java调用process线程阻塞问题的解决

    这篇文章主要介绍了java调用process线程阻塞问题的解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • springboot中如何通过main方法调用service或dao

    springboot中如何通过main方法调用service或dao

    这篇文章主要介绍了springboot中如何通过main方法调用service或dao,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • 解读@ConfigurationProperties使用时的几个常见误区

    解读@ConfigurationProperties使用时的几个常见误区

    在Spring Boot中,@ConfigurationProperties注解用于绑定配置文件中的属性到Java对象,它支持properties和yml文件格式,并且可以通过prefix属性指定配置属性的前缀,需要注意的是,@PropertySource注解默认只支持properties文件,不支持yml文件
    2024-10-10
  • Java中的数组流ByteArrayOutputStream用法

    Java中的数组流ByteArrayOutputStream用法

    Java中的ByteArrayOutputStream是java.io包中的一个类,用于在内存中创建字节数组缓冲区,支持动态扩展,它继承自OutputStream,允许以字节形式写入数据,无需与外部设备交互,常用方法包括write()、toByteArray()、toString()等
    2024-09-09
  • idea双击图标打不开,无反应的解决

    idea双击图标打不开,无反应的解决

    这篇文章主要介绍了idea双击图标打不开,无反应的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • 解决java junit单元测试@Test报错的问题

    解决java junit单元测试@Test报错的问题

    今天小编就为大家分享一篇解决java junit单元测试@Test报错的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-11-11

最新评论