Java八股文之-集合的特性

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

📦 什么是集合框架?

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

🔢 不同类型的集合

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

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

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

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

🔄 遍历集合

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

  1. 使用增强for循环

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

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

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

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

    • 你可以使用传统的for循环来遍历数组或List,通过索引访问元素。
    java 复制代码
    List<String> 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 实例,可能会导致数据丢失或不一致的问题。

线程安全

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

⚖️ 性能考虑

  1. ArrayList

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

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

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

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

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

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

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

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


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

相关推荐
也无晴也无风雨27 分钟前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
2401_857610034 小时前
多维视角下的知识管理:Spring Boot应用
java·spring boot·后端
代码小鑫4 小时前
A027-基于Spring Boot的农事管理系统
java·开发语言·数据库·spring boot·后端·毕业设计
颜淡慕潇5 小时前
【K8S问题系列 | 9】如何监控集群CPU使用率并设置告警?
后端·云原生·容器·kubernetes·问题解决
独泪了无痕6 小时前
WebStorm 如何调试 Vue 项目
后端·webstorm
怒放吧德德7 小时前
JUC从实战到源码:JMM总得认识一下吧
java·jvm·后端
代码小鑫7 小时前
A025-基于SpringBoot的售楼管理系统的设计与实现
java·开发语言·spring boot·后端·毕业设计
前端SkyRain7 小时前
后端SpringBoot学习项目-项目基础搭建
spring boot·后端·学习
梦想画家7 小时前
理解Rust 生命周期、所有权和借用机制
开发语言·后端·rust
编程乐趣8 小时前
推荐一个.NetCore开源的CMS项目,功能强大、扩展性强、支持插件的系统!
后端