当前位置: 首页 > ds >正文

Java集合框架入门指南:从小白到基础掌握

一、初识集合框架

当我们处理多个数据元素时,数组的固定长度和单一类型限制就显得不够灵活。这时Java集合框架(Collection Framework)就像智能收纳盒应运而生,它提供了更强大的数据存储和操作能力。

集合框架的核心优势:

  • 动态扩容:自动调整存储空间
  • 丰富操作:内置搜索、排序等方法
  • 类型安全:通过泛型保证数据一致性
  • 高效算法:优化过的数据结构实现

常用集合的分类:

单列集合Collection

Collection集合的方法

package com.jjt.Collection;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;public class Collection02 {public static void main(String[] args) {//集合的常用方法System.out.println("集合的常用方法");Collection<String> list = new ArrayList<>();//添加元素list.add("hello");list.add("world");list.add("java");list.add("c++");System.out.println(list);//删除元素list.remove("hello");System.out.println(list);//判断集合是否为空System.out.println(list.isEmpty());//清空集合//list.clear();//判断集合是否包含某个元素System.out.println(list.contains("java"));//集合转换成数组Object[] arr = list.toArray();System.out.println(Arrays.toString(arr));//获取集合的大小System.out.println(list.size());//将一个集合中的元素给到另一个集合Collection<String> list2 = new ArrayList<>();}
}

Java 单列集合框架梳理

一、List 家族

特点:元素有序、可重复、支持索引访问

  1. LinkedList

    • 基于双向链表实现
    • 插入/删除操作效率高($O(1)$)
    • 随机访问效率较低($O(n)$)
    • 非线程安全
  2. ArrayList

    • 基于动态数组实现
    • 随机访问效率高($O(1)$)
    • 增删操作可能触发数组扩容($O(n)$)
    • 非线程安全
  3. Vector

    • 基于数组实现的同步集合
    • 线程安全但性能较低
    • 扩容策略与ArrayList不同
  4. Stack

    • 继承自Vector
    • 实现后进先出(LIFO)栈结构
    • 核心方法: $$push(E), pop(), peek()$$

二、Set 家族

特点:元素唯一、不重复

  1. HashSet

    • 基于哈希表实现(HashMap)
    • 元素无序存储
    • 插入/查询效率高($O(1)$)
    • 允许存储null值
  2. LinkedHashSet

    • 继承HashSet
    • 通过链表维护插入顺序
    • 迭代顺序可预测
  3. TreeSet

    • 基于红黑树实现
    • 元素自然排序或定制排序
    • 插入/查询效率($O(\log n)$)
    • 实现NavigableSet接口

关键特性对比
集合类型数据结构有序性时间复杂度线程安全
ArrayList动态数组插入序O(1)随机
LinkedList双向链表插入序O(n)随机
HashSet哈希表无序O(1)
LinkedHashSet链表+哈希插入序O(1)
TreeSet红黑树排序序O(log n)

选择建议
  1. 需要快速随机访问 → ArrayList
  2. 频繁增删操作 → LinkedList
  3. 去重存储 → HashSet
  4. 保持插入顺序 → LinkedHashSet
  5. 自动排序需求 → TreeSet

Map 接口主要实现类对比及优化说明:

一、基础实现类

  1. Hashtable
  • 特性:同步处理、线程安全
  • 数据结构:数组+链表
  • 注意:键值不允许为 null,建议用 ConcurrentHashMap 替代
  1. HashMap
  • 特性:非同步、高效查询
  • 数据结构:数组+链表/红黑树(JDK8+)
  • 优化点:负载因子默认 0.75,扩容机制为 2 倍

二、有序实现类 3. LinkedHashMap

  • 特性:维护插入/访问顺序
  • 数据结构:哈希表+双向链表
  • 应用场景:缓存实现、顺序访问需求

三、特殊实现类 4. WeakHashMap

  • 特性:弱键引用机制
  • 内存管理:自动回收无引用的键值对
  • 应用场景:缓存临时映射
  1. TreeMap
  • 特性:按键自然排序或自定义排序
  • 数据结构:红黑树
  • 排序方式:实现 Comparable 或提供 Comparator
  1. IdentityHashMap
  • 特性:使用 == 代替 equals 比较键
  • 哈希策略:System.identityHashCode()
  • 应用场景:对象拓扑结构保持

四、选择建议

  • 并发场景:优先考虑 ConcurrentHashMap
  • 排序需求:根据排序类型选择 TreeMap 或 LinkedHashMap
  • 特殊比较:对象标识符处理使用 IdentityHashMap
  • 缓存场景:WeakHashMap 或 LinkedHashMap 配合移除策略

注:JDK8+ 中 HashMap 在哈希冲突时,链表长度超过 8 会自动转为红黑树结构(桶容量>64时),有效提升查询效率。


二、三大核心接口详解

1. List(有序集合)

特点:元素有序且可重复

// ArrayList示例
List<String> fruits = new ArrayList<>();
fruits.add("Apple");    // 索引0
fruits.add("Banana");   // 索引1
fruits.add(1, "Orange");// 在索引1插入
fruits.remove(int index)删除指定索引处的元素,返回被删除的元素
fruits.set(int index,e element) 修改指定索引处的元素,返回被修改的元素
fruits.get(int index)返回指定索引处的元素
System.out.println(fruits.get(2)); // 输出:Banana

实现类对比:功能差不多

  • ArrayList:数组实现,随机访问快
  • LinkedList:链表实现,插入删除快 查询慢,无论查询那个数据都要从头开始找。

2. Set(唯一集合)

特点:元素唯一且无序,不重复,无索引

// HashSet示例
Set<Integer> numbers = new HashSet<>();
numbers.add(5);
numbers.add(5);         // 重复元素不会被添加
System.out.println(numbers.size()); // 输出:1

常用实现:

  • HashSet:哈希表存储,查询速度O(1)---LinkedHashSet有序,不重复,无索引
  • TreeSet:红黑树实现,自动排序,默认升序排列
  • Vector:底层数据结构是数组,查询快,增删慢,线程安全,效率低,可以存储重复元素

1.Vector是线程同步的,所以它也是线程安全的,而ArrayList是线程异步的,是不安全的。如果不考虑到线程的安全因素,一般用ArrayList效率比较高。
2.如果集合中的元素的数目大于目前集合数组的长度时,在集合中使用数据量比较大的数据,用Vector有一定的优势。 

3. 自定义对象的去重

默认情况下,HashSet 通过 equals() 和 hashCode() 判断对象是否相等。
若自定义类未重写这两个方法,HashSet 无法正确去重

class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}// 重写 equals 和 hashCode@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person person = (Person) o;return age == person.age && Objects.equals(name, person.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}
}// 使用 HashSet 去重
Set<Person> people = new HashSet<>();
people.add(new Person("Alice", 20));
people.add(new Person("Alice", 20)); // 重复对象,添加失败

. 去重应用场景

  • 数据清洗:快速去除列表中的重复项。

  • 唯一性校验:确保数据(如用户 ID、订单号)唯一。

  • 集合操作:用于集合的交、并、差集运算。

         TreeSet集合

注意事项:对于数值类型:Integer,Double,默认按照数值本身的大小进行升序排序

对于字符串类型:默认按照首字符的编号升序排序

对于自定义类型如Student对象,无法直接排序。需要重写比较方法

1.对象类型实现Comparable比较接口,重写compareTo方法,指定大小比较规则2.TreeSet(Comparator c)集合自带比较器Comparator对象,

方式二:构造时传入 Comparator

     Set<Teacher> ts2 = new TreeSet<Teacher>(new Comparator<Teacher>() {@Overridepublic int compare(Teacher o1, Teacher o2) {return o1.getAge()-o2.getAge();}});

方式一:实现 Comparable 接口 

package com.jjt.Collection;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@AllArgsConstructor
@NoArgsConstructor
@Data
public class Teacher implements Comparable<Teacher>{private String name;private int age;private String sex;@Override//重写打印方法public String toString() {return "Teacher{" +"name='" + name + '\'' +", age=" + age +", sex='" + sex + '\'' +'}'+"\n";}//t1.compareTo(t2)实际两个对象比较@Overridepublic int compareTo(Teacher o) {//this调t1,o调t2//java默认//如果左边大于右边返回正整数//如果左边小于右边返回负整数//如果左边等于右边返回0//根据年龄排序升序,降序颠倒对象位置return this.age-o.age;}
}

 

3. Queue(队列)

特点:先进先出(FIFO)的线性表

Queue<String> queue = new LinkedList<>();
queue.offer("First");
queue.offer("Second");
System.out.println(queue.poll()); // 输出:First

三、集合工具类实战

1. 遍历集合的三种方式

Collection<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);
numbers.add(30);// 方法 1: 增强 for 循环
for (Integer num : numbers) {System.out.print(num + " "); // 10 20 30
}// 方法 2: 迭代器
Iterator<Integer> iterator = numbers.iterator();
while (iterator.hasNext()) {System.out.print(iterator.next() + " ");
}// 方法 3: Java 8 forEach
numbers.forEach(num -> System.out.print(num + " "));// 3. 迭代器
Iterator<String> it = colors.iterator();
while(it.hasNext()){
//hasNext判断有没有下一个System.out.println(it.next());
//next移动到下一个
}

1. 增强 for 循环 (Enhanced For Loop) 

  • 只读安全:遍历时不能直接删除或修改元素,否则会抛出 ConcurrentModificationException

  • 适用场景:快速遍历且无需修改集合内容。

2. 迭代器 (Iterator)

  • 支持安全修改:可通过 iterator.remove() 安全删除当前元素(唯一允许在遍历中删除元素的方式)。

  • 并发修改检测:如果在遍历过程中直接通过集合(如 collection.remove())修改集合,仍会抛出 ConcurrentModificationException

  • 适用场景:需要遍历时动态删除元素的场景(如过滤数据)。

 

2. 集合排序

List<Integer> nums = new ArrayList<>(Arrays.asList(3,1,4,2));// 自然排序
Collections.sort(nums); // [1,2,3,4]// 自定义排序
Collections.sort(nums, (a,b)->b-a); // [4,3,2,1]

四、实现类性能对比表

集合类型底层结构查询速度增删速度线程安全有序性
ArrayList数组O(1)O(n)有序
LinkedList链表O(n)O(1)有序
HashSet哈希表O(1)O(1)无序
TreeSet红黑树O(log n)O(log n)有序

五、最佳实践建议

  1. 快速查询选ArrayList,频繁增删用LinkedList
  2. 去重需求优先考虑HashSet
  3. 需要排序时使用TreeSet
  4. 多线程环境使用Collections.synchronizedList()包装
  5. 初始化时指定容量(如new ArrayList<>(100)

双列集合Map

三、Map 详解

Map(映射)是 Java 集合框架中用于存储键值对(Key-Value)数据的顶层接口,与 Collection 接口并列,不继承 Collection。其核心设计是通过唯一的键(Key)高效检索对应的值(Value),适用于需要精确键控访问的场景。


1. 核心特性

特性说明
键唯一性每个 Key 在 Map 中唯一,重复添加会覆盖旧 Value。
Value 可重复不同 Key 可映射到相同的 Value。
双列数据结构数据以 Entry<Key, Value> 形式存储,支持通过 Key 直接定位 Value。
允许 Null 值大多数实现类(如 HashMap)允许 Key 和 Value 为 null(具体取决于实现,如 Hashtable 禁止)。

2. Map vs Collection 数据结构对比

对比维度MapCollection
数据单元键值对(Key-Value)单元素(如 ListSet
存储方式通过哈希表、树等结构维护 Key 映射直接存储元素
核心操作put(key, value)get(key)add(element)remove(element)
唯一性约束Key 唯一Set 元素唯一,List 不唯一

3. Map 的三种集合视图

Map 提供三种视角访问其内容,均基于原 Map 动态更新

  1. Key 集合

    • 方法:Set<K> keySet()

    • 特点:返回所有 Key 的 Set 视图(因 Key 唯一)。

    Map<String, Integer> map = new HashMap<>();
    map.put("A", 1);
    map.put("B", 2);
    Set<String> keys = map.keySet(); // ["A", "B"]
  2. Value 集合

    • 方法:Collection<V> values()

    • 特点:返回所有 Value 的 Collection 视图(Value 可重复)。

    Collection<Integer> values = map.values(); // [1, 2]
  3. 键值对集合

    • 方法:Set<Entry<K, V>> entrySet()

    • 特点:返回所有 Entry(键值对)的 Set 视图,可直接操作 Key 和 Value。

    for (Map.Entry<String, Integer> entry : map.entrySet()) {System.out.println(entry.getKey() + ": " + entry.getValue());
    }

4. 常见实现类与选型建议

实现类底层结构特点适用场景
HashMap数组 + 链表/红黑树无序,查询高效(O(1)),允许 Null Key/Value,线程不安全。高频读写,无需排序。
LinkedHashMap链表 + 哈希表保留插入顺序或访问顺序(LRU),性能略低于 HashMap需要有序遍历的键值存储。
TreeMap红黑树Key 按自然顺序或自定义规则排序,操作时间复杂度 O(log n)。需要有序 Key 或范围查询。
ConcurrentHashMap分段锁 + CAS线程安全,高并发优化,性能接近 HashMap多线程环境下的高并发访问。
Hashtable哈希表线程安全(全表锁),性能低,不允许 Null Key/Value,已逐渐被淘汰。遗留系统兼容,不推荐新项目使用。

5. 关键注意事项

  1. 线程安全

    • HashMap 非线程安全,多线程环境下应使用 ConcurrentHashMapCollections.synchronizedMap() 包装类。

    • 示例:

      Map<String, Integer> safeMap = Collections.synchronizedMap(new HashMap<>());
  2. 哈希一致性

    • 若自定义对象作为 Key,必须正确重写 hashCode()equals() 方法,确保哈希计算和相等性判断准确。

  3. 遍历与修改

    • 直接通过集合视图(如 keySet())遍历时删除元素会抛出 ConcurrentModificationException,应使用迭代器的 remove() 方法。

    Iterator<Map.Entry<String, Integer>> it = map.entrySet().iterator();
    while (it.hasNext()) {Map.Entry<String, Integer> entry = it.next();if (entry.getKey().equals("A")) {it.remove(); // ✔️ 安全删除}
    }
  4. 性能优化

    • 初始化 HashMap 时指定容量和负载因子,减少扩容次数。

      Map<String, Integer> map = new HashMap<>(16, 0.75f);

6. 常见方法速查

方法作用
V put(K key, V value)添加键值对,若 Key 存在则覆盖并返回旧 Value。
V get(Object key)根据 Key 获取 Value,未找到返回 null
boolean containsKey(Object key)判断是否包含指定 Key。
V remove(Object key)删除指定 Key 的键值对,返回被删除的 Value。
default V getOrDefault(K key, V defaultValue)安全获取 Value,未找到时返回默认值(Java 8+)。
default void forEach(BiConsumer<? super K, ? super V> action)遍历所有键值对(Java 8+)。

 

一、基础操作

1. 添加/更新键值对
  • V put(K key, V value)

    • 作用:添加键值对。若 Key 已存在,则覆盖旧 Value,并返回旧 Value;若 Key 不存在,返回 null

    • 示例

      Map<String, Integer> map = new HashMap<>();
      map.put("A", 1);      // 返回 null
      map.put("A", 100);    // 返回 1,此时 Value 更新为 100
  • void putAll(Map<? extends K, ? extends V> m)

    • 作用:将另一个 Map 的所有键值对批量添加到当前 Map。

    • 示例

      Map<String, Integer> map1 = new HashMap<>();
      map1.put("B", 2);
      map.putAll(map1);     // map 变为 {"A":100, "B":2}

二、删除操作

  • V remove(Object key)

    • 作用:删除指定 Key 的键值对,返回被删除的 Value;若 Key 不存在,返回 null

    • 示例

      map.remove("B");      // 返回 2,map 变为 {"A":100}
  • default boolean remove(Object key, Object value)

    • 作用(Java 8+):仅当 Key 和 Value 都匹配时删除键值对,返回是否成功。

    • 示例

      map.remove("A", 1);   // 返回 false(当前 Value 是 100)
      map.remove("A", 100); // 返回 true,map 变为空
  • void clear()

    • 作用:清空所有键值对。

    • 示例

      map.clear();          // map 变为 {}

三、查询操作

  • V get(Object key)

    • 作用:根据 Key 获取 Value;若 Key 不存在,返回 null

    • 示例

      map.get("A");         // 返回 100
  • boolean containsKey(Object key)

    • 作用:判断 Map 是否包含指定 Key。

    • 示例

      map.containsKey("A"); // 返回 true
  • boolean containsValue(Object value)

    • 作用:判断 Map 是否包含指定 Value。

    • 示例

      map.containsValue(100); // 返回 true
  • int size()

    • 作用:返回键值对的数量。

    • 示例

      map.size();            // 返回 1
  • boolean isEmpty()

    • 作用:判断 Map 是否为空。

    • 示例

      map.isEmpty();         // 返回 false

四、视图方法

  • Set<K> keySet()

    • 作用:返回所有 Key 的 Set 视图(可遍历或删除元素)。

    • 示例

      Set<String> keys = map.keySet(); // ["A"]
  • Collection<V> values()

    • 作用:返回所有 Value 的 Collection 视图(可遍历或删除元素)。

    • 示例

      Collection<Integer> values = map.values(); // [100]
  • Set<Map.Entry<K, V>> entrySet()

    • 作用:返回所有键值对的 Set<Entry> 视图,支持遍历或修改 Value。

    • 示例

      for (Map.Entry<String, Integer> entry : map.entrySet()) {entry.setValue(entry.getValue() + 10); // 修改 Value
      }

五、Java 8+ 新增方法

  • default V getOrDefault(Object key, V defaultValue)

    • 作用:安全获取 Value,若 Key 不存在则返回默认值。

    • 示例

      map.getOrDefault("C", 0); // 返回 0
  • default V putIfAbsent(K key, V value)

    • 作用:仅当 Key 不存在时添加键值对,返回旧 Value 或 null

    • 示例

      map.putIfAbsent("A", 200); // 返回 100(不覆盖)
      map.putIfAbsent("C", 3);   // 返回 null,添加成功
  • default boolean replace(K key, V oldValue, V newValue)

    • 作用:仅当 Key 和旧 Value 匹配时,更新为新 Value。

    • 示例

      map.replace("A", 100, 200); // 返回 true
  • default V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)

    • 作用:根据 Key 和旧 Value 计算新 Value,若计算结果为 null,则删除该 Key。

    • 示例(将 Value 加倍):

      map.compute("A", (k, v) -> v * 2); // Value 变为 200
  • default V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction)

    • 作用:合并新旧 Value(常用于累加或去重)。

    • 示例(合并字符串):

      Map<String, String> map = new HashMap<>();
      map.merge("A", "Hello", (oldVal, newVal) -> oldVal + newVal); // "Hello"
      map.merge("A", "World", (oldVal, newVal) -> oldVal + newVal); // "HelloWorld"
  • default void forEach(BiConsumer<? super K, ? super V> action)

    • 作用:遍历所有键值对。

    • 示例

      map.forEach((k, v) -> System.out.println(k + ": " + v));

六、批量操作

  • default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function)

    • 作用(Java 8+):对所有键值对应用函数替换 Value。

    • 示例(所有 Value 加倍):

      map.replaceAll((k, v) -> v * 2);

七、线程安全方法

  • ConcurrentHashMap 的原子操作(非 Map 接口通用方法,但需注意):

    • V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)

    • V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)


总结

方法分类核心方法
增/改put(), putAll(), putIfAbsent()
remove(), clear()
get(), containsKey(), containsValue(), size(), isEmpty()
视图keySet(), values(), entrySet()
Java 8+getOrDefault(), compute(), merge(), forEach(), replaceAll()
并发安全ConcurrentHashMap 的原子方法(需具体实现类支持)

最佳实践

  1. 优先使用 getOrDefault:避免 null 导致的空指针异常。

  2. 遍历优化:使用 entrySet() 遍历而非多次调用 get()(减少哈希计算开销)。

  3. 线程安全:多线程环境下选择 ConcurrentHashMap 而非 Collections.synchronizedMap()

总结

Map 是键值对存储的核心接口,通过唯一 Key 实现高效检索。根据场景选择合适的实现类(如高频读写用 HashMap,有序需求用 TreeMap),并注意线程安全、哈希一致性和遍历安全性问题。

总结

集合框架的学习就像搭建积木,理解各个组件的特点后,就能根据需求灵活组合。建议通过以下步骤巩固:

  1. 手写各集合的CRUD操作
  2. 比较不同实现类的性能差异
  3. 尝试实现自定义对象的排序
  4. 探索Map接口及其实现类

记得在实际编码中多使用Java Doc(Ctrl+Q查看方法说明),逐步培养选择合适集合类型的能力。

http://www.xdnf.cn/news/8272.html

相关文章:

  • 聚水潭ERP(奇门)集成用友ERP(用友U8、U9、NC、BIP、畅捷通T+、好业财)
  • 位图算法——判断唯一字符
  • 百度智能云千帆AppBuilder RAG流程技术文档
  • 佰力博科技与您探讨半导体电阻测试常用的一些方法
  • Qt 布局管理器的层级关系
  • 【I2C】高效实现I2C寄存器读取函数
  • 如何免费申请SSL证书并无限续期!
  • 使用Node开发需要知道的背景知识
  • 基于机器学习的策略开发和Backtrader回测
  • “2025香港国际法律服务大会探讨“跨法域 链全球”新格局”
  • 基于LangManus深入理解系统提示设计
  • Origin绘制多因子柱状点线图
  • 0x90属性中的属性名$I30和Scb->AttributeName的关系
  • day19-20-四剑客-find-grep-sed-awk
  • OpenCV CUDA 模块图像过滤-----创建一个计算图像导数的滤波器函数createDerivFilter()
  • 深入剖析小红书笔记详情接口:技术原理与实战应用
  • 技术篇-2.1.C\C++应用场景及开发工具安装
  • Python训练营打卡——DAY33(2025.5.22)
  • 并发编程之异步线程池
  • 【运维实战】Python打造基于免费API的IP地址归属地批量查询工具!
  • 5.0.6 TreeView的使用介绍
  • find-chomd-read-ls和ll的区别
  • Crawl4AI:高效的AI数据抓取工具
  • Spring概念问题详解
  • [C++面试] 基础题
  • springboot 集成kerberos 用户认证 获取域账号
  • 完整改进RIME算法,基于修正多项式微分学习算子Rime-ice增长优化器,完整MATLAB代码获取
  • 【数据结构】 栈和队列
  • 微软全新开源的Agentic Web网络项目:NLWeb,到底是什么 ?
  • 鸿蒙App开发学习路径