37-Java 集合框架

Java 集合框架(Java Collections Framework,简称 JCF)是 Java 提供的一套标准化的数据结构和算法的库,用于存储和操作一组对象。集合框架提供了丰富的接口和实现类,能够满足各种数据存储和操作需求。


1. 集合框架的概述

1.1 什么是集合?

  • 集合 是一种容器,用于存储一组数据元素(对象)。
  • 与数组不同,集合的大小是可动态扩展的,可以存储不同类型的数据对象。

1.2 集合框架的核心组件

Java 集合框架主要分为以下三大部分:

  1. 接口(Interfaces)
    • 定义了集合的基本行为和操作。
    • CollectionListSetMap 等。
  2. 实现类(Implementations)
    • 提供了具体的集合实现。
    • ArrayListHashSetHashMap 等。
  3. 算法(Algorithms)
    • 提供了一些通用的操作集合的方法。
    • 如排序、搜索、遍历等,通常在 Collections 工具类中实现。

2. 集合框架的层次结构

Java 集合框架是以接口为核心设计的,其层次结构如下:

java.util.Collection (接口)
    ├── List (接口)
    │     ├── ArrayList (实现类)
    │     ├── LinkedList (实现类)
    │     └── Vector (实现类)
    │           └── Stack (实现类)
    ├── Set (接口)
    │     ├── HashSet (实现类)
    │     ├── LinkedHashSet (实现类)
    │     └── TreeSet (实现类)
    └── Queue (接口)
          ├── PriorityQueue (实现类)
          └── LinkedList (实现类)
          
java.util.Map (接口)
    ├── HashMap (实现类)
    ├── LinkedHashMap (实现类)
    ├── TreeMap (实现类)
    └── Hashtable (实现类)
          └── Properties (实现类)

3. Collection 接口及其子接口

3.1 Collection 接口

  • Collection 是所有集合接口的根接口。
  • 它定义了一些通用操作方法,如添加元素、删除元素、判断集合是否为空等。
常用方法
方法描述
boolean add(E e)添加元素到集合中。
boolean remove(Object o)从集合中删除指定元素。
int size()返回集合中元素的数量。
boolean isEmpty()判断集合是否为空。
boolean contains(Object o)判断集合是否包含指定元素。
Iterator<E> iterator()返回集合的迭代器。
void clear()清空集合中的所有元素。

3.2 List 接口

  • 特点:有序集合,允许重复元素。
  • 实现类
    • ArrayList:基于动态数组,读取效率高,插入和删除效率较低。
    • LinkedList:基于双向链表,插入和删除效率高。
    • Vector:线程安全,性能较低,已不推荐使用。
示例:ArrayList
import java.util.ArrayList;

public class ArrayListExample {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();

        // 添加元素
        list.add("Alice");
        list.add("Bob");
        list.add("Charlie");

        // 遍历集合
        for (String name : list) {
            System.out.println(name);
        }

        // 删除元素
        list.remove("Bob");
        System.out.println("删除后: " + list);
    }
}

3.3 Set 接口

  • 特点:无序集合,不允许重复元素。
  • 实现类
    • HashSet:基于哈希表,无序。
    • LinkedHashSet:基于哈希表和链表,有插入顺序。
    • TreeSet:基于红黑树,元素有序。
示例:HashSet
import java.util.HashSet;

public class HashSetExample {
    public static void main(String[] args) {
        HashSet<Integer> set = new HashSet<>();

        // 添加元素
        set.add(10);
        set.add(20);
        set.add(10); // 重复元素不会被添加

        System.out.println("集合: " + set);

        // 检查元素是否存在
        System.out.println("包含 20? " + set.contains(20));
    }
}

3.4 Queue 接口

  • 特点:用于存储需要处理的元素,支持先进先出(FIFO)的操作。
  • 实现类
    • LinkedList:既可作为队列,也可作为双端队列。
    • PriorityQueue:基于优先级的队列,元素按优先级排序。
示例:PriorityQueue
import java.util.PriorityQueue;

public class PriorityQueueExample {
    public static void main(String[] args) {
        PriorityQueue<Integer> pq = new PriorityQueue<>();

        // 添加元素
        pq.offer(30);
        pq.offer(10);
        pq.offer(20);

        // 按优先级出队
        while (!pq.isEmpty()) {
            System.out.println(pq.poll());
        }
    }
}

4. Map 接口及其实现

Map 是一个键值对(Key-Value)集合,键唯一,值可以重复。

4.1 Map 的实现类

实现类特点
HashMap基于哈希表实现,无序,允许一个 null 键和多个 null 值。
LinkedHashMap保留插入顺序。
TreeMap基于红黑树实现,键按自然顺序或自定义比较器排序。
Hashtable线程安全,但性能较低,不允许键或值为 null
示例:HashMap
import java.util.HashMap;

public class HashMapExample {
    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>();

        // 添加键值对
        map.put("Alice", 25);
        map.put("Bob", 30);
        map.put("Charlie", 35);

        // 遍历 Map
        for (String key : map.keySet()) {
            System.out.println(key + " -> " + map.get(key));
        }

        // 删除键值对
        map.remove("Bob");
        System.out.println("删除后: " + map);
    }
}

5. Collections 工具类

Collections 是 Java 提供的一个工具类,包含了操作集合的常用方法,如排序、搜索和线程安全包装。

常用方法
方法描述
Collections.sort(List<T> list)对列表进行升序排序。
Collections.reverse(List<T> list)反转列表中的元素顺序。
Collections.shuffle(List<T> list)随机打乱列表中的元素顺序。
Collections.synchronizedList()返回线程安全的 List
Collections.max(Collection<T>)返回集合中的最大值。
示例:排序和线程安全
import java.util.ArrayList;
import java.util.Collections;

public class CollectionsExample {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(3);
        list.add(1);
        list.add(2);

        // 排序
        Collections.sort(list);
        System.out.println("排序后: " + list);

        // 随机打乱
        Collections.shuffle(list);
        System.out.println("打乱后: " + list);

        // 获取最大值
        System.out.println("最大值: " + Collections.max(list));
    }
}

6. 集合框架的特点

6.1 优点

  • 统一接口:所有集合类使用相同的操作方法,如 add()remove()
  • 灵活性:支持动态扩展,克服了数组的固定大小限制。
  • 多种实现:提供了不同的实现,适合各种场景(如有序、无序、线程安全等)。
  • 线程安全支持:提供了线程安全的集合实现,如 VectorConcurrentHashMap

6.2 缺点

  • 性能开销:相比数组,集合类的性能稍逊,因为它们支持动态扩展和更多功能。
  • 类型安全(Java 5 之前):早期版本的集合类不支持泛型,容易发生类型转换问题。

7. 总结

Java 集合框架提供了一整套高效、灵活的数据结构和算法工具,能够满足各种开发需求:

  1. 核心接口

    • Collection:基础接口。
    • ListSetQueue:具体子接口。
    • Map:键值对集合。
  2. 常见实现

    • 动态数组:ArrayList
    • 链表:LinkedList
    • 哈希表:HashMap
    • 有序集合:TreeSetTreeMap
  3. 工具类

    • Collections 提供了排序、同步包装等便捷方法。

在实际开发中,根据数据特性和需求选择合适的集合类型,可以显著提高代码的性能和可读性。


Java 集合框架的高级特性与扩展

在前面介绍了 Java 集合框架的基础知识后,我们继续探讨集合框架的一些高级特性、并发集合、常见性能比较,以及如何根据实际场景选择合适的集合类型。


8. 并发集合(Concurrent Collections)

在多线程环境中,普通集合(如 ArrayListHashMap)是线程不安全的,多个线程同时操作可能会导致数据不一致。为了解决这一问题,Java 提供了 并发集合类,它们位于 java.util.concurrent 包中。


8.1 并发集合的优势

  • 线程安全:通过内部加锁或无锁机制实现线程安全。
  • 高性能:相比早期的线程安全集合(如 VectorHashtable),并发集合采用了更高效的机制(如分段锁、CAS 操作等)。
  • 非阻塞操作:某些并发集合支持无锁算法(如 ConcurrentLinkedQueue)。

8.2 常用的并发集合

特点
ConcurrentHashMap高效线程安全的哈希表,支持并发读写,性能高于 Hashtable
CopyOnWriteArrayList线程安全的动态数组,写操作时会复制整个数组,适合读多写少的场景。
ConcurrentLinkedQueue基于无锁算法的线程安全队列,支持高效的并发操作。
LinkedBlockingQueue基于链表的阻塞队列,支持生产者-消费者模式。
ConcurrentSkipListMap基于跳表实现的线程安全有序映射,键值对按自然顺序或自定义比较器排序。
ConcurrentSkipListSet基于跳表实现的线程安全有序集合。

8.3 示例:ConcurrentHashMap

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

        // 添加元素
        map.put("Alice", 100);
        map.put("Bob", 200);

        // 多线程操作
        Thread t1 = new Thread(() -> map.put("Charlie", 300));
        Thread t2 = new Thread(() -> map.put("Dave", 400));

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 遍历集合
        map.forEach((key, value) -> System.out.println(key + " -> " + value));
    }
}

输出示例

Alice -> 100
Bob -> 200
Charlie -> 300
Dave -> 400

8.4 示例:CopyOnWriteArrayList

import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteArrayListExample {
    public static void main(String[] args) {
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();

        // 添加元素
        list.add("Alice");
        list.add("Bob");

        // 遍历期间修改
        for (String name : list) {
            System.out.println(name);
            list.add("Charlie"); // 不会影响当前遍历
        }

        System.out.println("最终列表: " + list);
    }
}

输出

Alice
Bob
最终列表: [Alice, Bob, Charlie]

9. 集合框架的性能比较

在选择集合类时,需要根据具体场景(如数据量、操作类型、多线程等)来决定。以下是常见集合的性能对比和适用场景:


9.1 List 的性能比较

实现类随机访问插入/删除(中间位置)线程安全适用场景
ArrayList快(O(1))慢(O(n))适合频繁读取的场景。
LinkedList慢(O(n))快(O(1))适合频繁插入和删除的场景。
CopyOnWriteArrayList慢(O(n))慢(O(n))适合多线程读多写少的场景。

9.2 Set 的性能比较

实现类查找速度插入/删除有序性线程安全适用场景
HashSet快(O(1))快(O(1))无序适合快速查找唯一元素的场景。
LinkedHashSet快(O(1))快(O(1))按插入顺序排序需要插入顺序时使用。
TreeSet慢(O(log n))慢(O(log n))按自然顺序排序需要排序的场景。
ConcurrentSkipListSet慢(O(log n))慢(O(log n))按自然顺序排序多线程环境下的有序集合。

9.3 Map 的性能比较

实现类查找速度插入/删除有序性线程安全适用场景
HashMap快(O(1))快(O(1))无序适合快速查找键值对的场景。
LinkedHashMap快(O(1))快(O(1))按插入顺序排序需要按插入顺序遍历键值对时使用。
TreeMap慢(O(log n))慢(O(log n))按自然顺序排序需要键自动排序时使用。
ConcurrentHashMap快(O(1))快(O(1))无序多线程环境下的高效键值对存储。
ConcurrentSkipListMap慢(O(log n))慢(O(log n))按自然顺序排序多线程环境下需要排序的键值对存储。

10. 集合框架的扩展与高级技巧

10.1 使用泛型

Java 集合框架支持泛型,可以在编译时检查类型,从而避免运行时的类型转换异常。

示例:使用泛型
import java.util.ArrayList;
import java.util.List;

public class GenericsExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Alice");
        list.add("Bob");

        // 遍历集合,无需类型转换
        for (String name : list) {
            System.out.println(name);
        }
    }
}

10.2 自定义排序

使用 ComparatorComparable 接口可以对集合中的元素进行自定义排序。

示例:Comparator 自定义排序
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class CustomSortExample {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("Charlie");
        list.add("Alice");
        list.add("Bob");

        // 按字符串长度排序
        Collections.sort(list, Comparator.comparingInt(String::length));

        System.out.println(list); // 输出: [Bob, Alice, Charlie]
    }
}

10.3 集合的不可变性

Java 提供了 Collections.unmodifiableList() 等方法,创建只读集合,防止修改。

示例:不可变集合
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;

public class UnmodifiableListExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Alice");
        list.add("Bob");

        // 创建不可变集合
        List<String> unmodifiableList = Collections.unmodifiableList(list);

        // 尝试修改将抛出异常
        // unmodifiableList.add("Charlie"); // UnsupportedOperationException
    }
}

10.4 使用 Streams 操作集合

Java 8 引入了 Stream API,可以对集合进行高效的数据处理。

示例:Stream 操作集合
import java.util.ArrayList;
import java.util.List;

public class StreamExample {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);

        // 使用 Stream 过滤和映射
        numbers.stream()
               .filter(n -> n > 1) // 过滤大于 1 的元素
               .map(n -> n * 2)    // 每个元素乘以 2
               .forEach(System.out::println); // 输出结果
    }
}

输出

4
6

11. 总结与实践建议

11.1 集合框架的核心点

  1. 灵活性:支持多种数据结构(如列表、集合、队列、映射)。
  2. 线程安全支持:提供线程安全的集合(如 ConcurrentHashMap)。
  3. 泛型支持:提高代码的类型安全性。
  4. 工具类支持CollectionsStreams 提供了丰富的操作方法。

11.2 实践建议

  1. 选择合适的集合
    • 频繁读取:ArrayList
    • 频繁插入/删除:LinkedList
    • 无序唯一:HashSet
    • 有序唯一:TreeSet
  2. 多线程环境
    • 使用并发集合(如 ConcurrentHashMap)。
  3. 性能优化
    • 如果集合大小已知,初始化时指定容量,减少扩容开销。
  4. 简化操作
    • 使用 Stream API 处理集合数据,代码更简洁。

熟练掌握 Java 集合框架,结合实际场景选择合适的实现,可以帮助开发者编写高效、健壮的代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小宝哥Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值