java集合进阶

一、常用集合底层数据结构

  1. ArrayList

    底层:动态扩容数组

    特点:连续内存、下标随机访问快;中间 / 首尾增删需要移位,效率低。

  2. LinkedList

    底层:双向循环链表

    特点:无连续内存、无扩容;首尾增删极快;随机查询慢,需遍历节点。

  3. HashMap(JDK1.8)

    底层:哈希数组 + 单向链表 + 红黑树

​ 链表长度≥8 & 数组容量≥64 → 树化

​ 红黑树节点≤6 → 退化为链表

  1. HashSet

    底层:内部直接包装 HashMap

存入 Set 的元素,作为 HashMap 的 key,value 统一为静态常量占位值。


二、集合线程安全问题

1. 哪些是线程不安全集合

List:ArrayListLinkedList

Set:HashSetLinkedHashSet

Map:HashMapLinkedHashMap

多线程并发读写(并发 add/put、扩容、遍历删除)会出现:数据覆盖、丢失、死循环、ConcurrentModificationException

2. 如何转为线程安全

1)古老方式(不推荐)

1
2
List<String> list = Collections.synchronizedList(new ArrayList<>());
Map map = Collections.synchronizedMap(new HashMap<>());

底层:方法加 synchronized,全局锁,性能差。

2)并发推荐(JUC)

  • List → CopyOnWriteArrayList
  • Set → CopyOnWriteArraySet
  • Map → ConcurrentHashMap

3. CopyOnWriteArrayList 核心原理

  1. 写时复制:修改(add/set/remove)时,先复制一份新数组

  2. 在新数组上完成修改,再替换原数组

  3. 读操作不加锁、完全并发;写操作加锁

  4. 适用:读多写少 场景

    缺点:频繁写入会大量复制数组,内存开销大。


三、两大比较器(对象排序必备)

1. Comparable 自然排序(内部比较器)

  • 位于:java.lang
  • 写法:实体类直接实现接口,重写 compareTo()
  • 耦合度高,排序规则写死在实体类
1
2
3
4
5
6
7
8
public class User implements Comparable<User>{
private int age;
@Override
public int compareTo(User o) {
// 升序:this.age - o.age
return this.age - o.age;
}
}

2. Comparator 定制排序(外部比较器)

  • 位于:java.util
  • 临时规则、灵活、解耦,不修改原实体类
  • 常用于集合排序、Stream 排序
1
2
// 按年龄降序
Collections.sort(list, (u1,u2) -> u2.getAge() - u1.getAge());

记忆口诀

  • Comparable:自己和自己比(内部)
  • Comparator:第三方帮忙比(外部)

四、Java8 Stream 流(集合操作神器)

核心作用

简化集合遍历、过滤、排序、去重、分组、统计、聚合,链式编程,代码极简

常用核心操作(直接上手)

1. 过滤 filter

1
2
// 只保留大于18的用户
list.stream().filter(u -> u.getAge() > 18).collect(Collectors.toList());

2. 排序 sorted

1
2
// 年龄升序
list.stream().sorted(Comparator.comparing(User::getAge)).collect(Collectors.toList());

3. 去重 distinct

1
list.stream().distinct().collect(Collectors.toList());

4. 分组 groupBy(开发高频)

1
2
3
// 按年龄分组,key=年龄,value=同年龄集合
Map<Integer, List<User>> groupMap =
list.stream().collect(Collectors.groupingBy(User::getAge));

5. 聚合统计(求和、最大、最小、平均值)

1
2
IntStream.of(1,2,3).sum();
list.stream().mapToInt(User::getAge).max();

Stream 三阶段

  1. 串行 / 并行流获取:stream() / parallelStream()
  2. 中间操作(延迟执行):filter、map、sorted、distinct
  3. 终结操作(触发执行):collect、forEach、count、max

java集合进阶
http://hanqichuan.com/2022/07/11/java集合/java集合进阶/
作者
韩启川
发布于
2022年7月11日
许可协议