Java八股文之集合的特性

2023年 9月 26日 85.4k 0

JAVA集合框架是每个开发者都绕不开的话题,也是我们要熟练掌握的核心之一,它为我们提供了一整套强大的工具,用于存储、组织和操作数据。让我们一起来深入了解这个重要的主题。

📦 什么是集合框架?

Java 集合框架是一组接口、类和算法的集合,用于处理和管理数据。它提供了多种数据结构,包括 List、Set、Map 等,以满足不同场景下的需求。

🔢 不同类型的集合

  • List: 有序集合,允许重复元素。例如 ArrayList、LinkedList、Vector。

  • Set: 无序集合,不允许重复元素。例如 HashSet、LinkedHashSet、TreeSet。

  • Map: 键值对的集合。例如 HashMap、LinkedHashMap、TreeMap。

  • 附上一张我自己整理的图

Java 中常用的容器_集合框架有哪些?.png

🔄 遍历集合

在Java中,你可以使用多种方式来遍历集合。以下是5种常用的遍历集合的方式:

  • 使用增强for循环:

    • 增强for循环(也称为for-each循环)是一种简单的遍历集合的方式。它适用于所有实现了Iterable接口的集合,包括数组、List、Set等。
    List list = new ArrayList();
    for (String item : list) {
        System.out.println(item);
    }
    
  • 使用迭代器(Iterator):

    • 迭代器是一种更通用的遍历方式,适用于所有实现了Iterable接口的集合。它允许你在遍历过程中删除元素。
    List list = new ArrayList();
    Iterator iterator = list.iterator();
    while (iterator.hasNext()) {
        String item = iterator.next();
        System.out.println(item);
    }
    
  • 使用Java 8的Stream API:

    • Java 8引入的Stream API提供了强大的集合处理功能,包括过滤、映射、归约等操作。你可以使用forEach方法来遍历元素。
    List list = new ArrayList();
    list.stream().forEach(item -> System.out.println(item));
    
  • 使用Lambda表达式和方法引用:

    • Java 8还引入了Lambda表达式和方法引用,可以简化遍历集合的代码。
    List list = new ArrayList();
    list.forEach(System.out::println); // 使用方法引用
    
  • 使用传统的for循环:

    • 你可以使用传统的for循环来遍历数组或List,通过索引访问元素。
    List list = new ArrayList();
    for (int i = 0; i < list.size(); i++) {
        String item = list.get(i);
        System.out.println(item);
    }
    
  • 不同的遍历方式适用于不同的情况和需求。通常来说,增强for循环和Stream API更加简洁和易读,而迭代器适用于需要在遍历过程中删除元素的情况,传统for循环则适用于数组和需要访问索引的情况。选择适合自己的才是最重要的。

    🚧 线程安全性

    线程非安全

    • ArrayList:ArrayList 不是线程安全的,多个线程同时修改一个 ArrayList 实例可能导致不一致的状态。
    • HashMap:HashMap 也是非线程安全的。多线程环境下,如果多个线程同时修改一个 HashMap 实例,可能会导致数据丢失或不一致的问题。

    线程安全

    • Vector:Vector 是线程安全的 List 实现,可以确保多个线程安全地访问和修改它。
    • HashTable:HashTable 是线程安全的 Map 实现,类似于 HashMap,但它的方法都是同步的,因此可以在多线程环境下使用。
    • Collections 类的静态方法来包装非线程安全的集合,使其变为线程安全。例如,Collections.synchronizedListCollections.synchronizedMap 可以用来包装 ArrayListHashMap,生成一个线程安全的 ListMap
    • ConcurrentHashMap:ConcurrentHashMap 是 Java 5 引入的高度并发的线程安全的 Map 实现,支持高度并发读写操作,性能比 HashTable 好(看了源码就会了解:ConcurrentHashMap采用的是分段锁,而HashTable底层使用的是通过synchronized来保证线程安全的)。

    ⚖️ 性能考虑

  • ArrayList:

    • 插入:在列表末尾进行插入操作的性能非常高,因为它的底层是数组。平均时间复杂度为 O(1)。
    • 查询:随机访问元素的性能很好,因为可以通过索引进行快速访问,平均时间复杂度为 O(1)。但在列表的开头或中间插入或删除元素时,可能需要移动后续元素,导致较差的性能。
  • LinkedList:

    • 插入:在列表的开头或中间进行插入操作的性能较好,因为它是基于链表实现的,插入元素只需要改变节点的引用。平均时间复杂度为 O(1)。
    • 查询:随机访问元素的性能较差,因为需要遍历链表来查找元素,平均时间复杂度为 O(n)。但在列表的开头或中间插入或删除元素时,性能较好。
  • HashSet:

    • 插入:插入元素的性能通常很好,因为它是基于哈希表实现的,插入元素的平均时间复杂度为 O(1)。
    • 查询:查找元素的性能也很好,平均时间复杂度为 O(1)。但在哈希冲突发生时,性能可能会下降,因为需要在冲突的链表上进行线性查找。
  • TreeSet:

    • 插入:插入元素的性能较好,平均时间复杂度为 O(log n),因为它是基于红黑树实现的。
    • 查询:查找元素的性能也较好,平均时间复杂度为 O(log n)。
  • HashMap:

    • 插入:插入键值对的性能通常很好,平均时间复杂度为 O(1)。但在哈希冲突发生时,性能可能会下降。
    • 查询:查找键对应的值的性能也很好,平均时间复杂度为 O(1)。但在哈希冲突发生时,性能可能会下降,需要线性查找。
  • TreeMap:

    • 插入:插入键值对的性能较好,平均时间复杂度为 O(log n),因为它是基于红黑树实现的。
    • 查询:查找键对应的值的性能也较好,平均时间复杂度为 O(log n)。
  • ConcurrentHashMap:

    • 插入和查询:ConcurrentHashMap 在高并发环境中表现良好,多个线程可以同时插入和查询,性能较好。它通过分段锁来实现并发性。

    tips:具体使用哪种需要结合业务的实际情况考虑,如果需要高性能插入和查询操作,不用保持元素顺序的情况下使用HashSetHashMap,如果需要有序的集合,则可以使用TreeSetTreeMap,如果是在多线程情况下则使用ConcurrentHashMap较为合适。

  • 此篇我们主要介绍了集合框架有哪些遍历方式线程安全性能多方面介绍了集合框架的基础信息,由于篇幅有限,我们下章会着重介绍相关集合的相关面试题,有需要的小伙伴可以点赞关注哦。

    相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论