Java面试

ArrayList‌

默认初始容量为10,无参构造时首次添加元素扩容至10
后续扩容按旧容量的1.5倍计算(newCapacity = oldCapacity + (oldCapacity >> 1))
若扩容后仍不足,则直接采用所需最小容量

Vector‌

默认初始容量为10,扩容策略与ArrayList类似但默认扩容为旧容量的2倍
支持通过构造器指定容量增量(capacityIncrement)

HashMap/HashSet‌

默认初始容量16(HashMap),负载因子0.75
扩容触发条件:元素数 > 容量 × 负载因子(如16×0.75=12)
扩容后容量为旧容量的2倍
条件 1:某个桶下的链表长度,达到阈值 8(默认值,源码里的TREEIFY_THRESHOLD);
条件 2:整个 HashMap 的数组长度,达到阈值 64(默认值,源码里的MIN_TREEIFY_CAPACITY)。

Hashtable

初始容量11
扩容加载因子(0.75)
当超出默认长度(int)(11*0.75)=8时,
扩容为oldx2+1。新容量为原容量的2倍+1.

LinkedList‌

基于双向链表实现,无需扩容机制

LinkedHashMap‌

继承HashMap,扩容规则相同但保留元素插入顺序
特殊场景‌:
addAll(Collection c)会取Math.max(原容量1.5倍, 实际元素数)作为新容量
最大容量限制为Integer.MAX_VALUE - 8(部分集合类)

TreeMap

虽然TreeMap的实现细节与HashMap不同(它使用红黑树而不是哈希表),但它的扩容机制类似于HashMap:
初始容量:默认情况下,TreeMap的初始容量与HashMap相同,为16。
加载因子:与HashMap相同,默认为0.75。
扩容机制:当元素数量超过当前容量的加载因子时,会进行扩容,新的容量是旧容量的两倍

在Java中,若需线程安全的ArrayList替代方案,主要有以下三种实现方式:

  1. ‌Vector类‌
‌特点‌:JDK1.0提供的线程安全动态数组,所有方法通过synchronized同步,但性能较差
‌问题‌:锁粒度粗(方法级同步),高并发场景效率低,现代开发已不推荐使用
  1. ‌Collections.synchronizedList‌
‌实现‌:通过工具类包装普通ArrayList,返回同步列表
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
‌注意点‌:
迭代器操作需手动加锁,否则可能抛出ConcurrentModificationException
性能优于Vector,但仍存在同步开销
  1. ‌CopyOnWriteArrayList(推荐)‌
‌原理‌:基于写时复制(Copy-On-Write),读操作无锁,写操作复制新数组修改
List<String> cowList = new CopyOnWriteArrayList<>();
‌优势‌:
读多写少场景性能极高,适合监听器列表等高频读取场景
迭代器弱一致性,避免并发修改异常
‌缺点‌:
写操作内存开销大(需复制整个数组)

java有了基础类型 为什么还要有包装类

一、面向对象特性支持
基本数据类型不是对象,无法直接参与面向对象的操作(如多态、集合存储等)。包装类将基本类型封装为对象,使其具备对象特性
例如ArrayList<Integer>可以存储整型数据,而ArrayList<int>会编译错误
二、集合框架与泛型需求
Java集合框架(如List、Map)和泛型仅支持对象类型。包装类通过自动装箱/拆箱机制实现基本类型与集合的兼容
例如:
List<Integer> list = Arrays.asList(1, 2, 3); // 自动装箱为Integer对象
三、功能扩展
包装类提供丰富的工具方法,如类型转换(Integer.parseInt())、进制转换(Integer.toBinaryString())等,弥补了基本类型的功能缺失
四、NULL值处理
包装类默认值为null,适用于POJO属性和数据库交互场景。基本类型无法表示缺失值,强制使用可能导致NullPointerException
例如数据库查询结果可能为null,使用Integer能安全处理
五、内存与性能权衡
虽然包装类占用更多内存(堆存储),但JVM对常用值(-128~127)做了缓存优化(如IntegerCache),平衡了性能与功能需求基本类型则在计算密集型场景更高效
六、特殊场景支持
‌反射与注解‌:包装类支持运行时类型检查
‌泛型约束‌:如<T extends Number>只能使用包装类
‌API兼容‌:如Collections.sort()必须接收对象列表

hashMap为啥用红黑树

1:HashMap 用 “数组 + 链表” 解决哈希冲突,但长链表会让查询效率从 O (1) 退化到 O (n);

2:红黑树的查询效率是 O (log n),用它替代长度≥8 的链表,能保证冲突严重时依然高效;

3:加数组长度≥64 的限制,是因为优先通过扩容分散元素,避免过早转树增加复杂度 —— 本质是 “平衡查询效率和结构维护成本
posted @ 2025-08-29 09:31  朝阳1  阅读(6)  评论(0)    收藏  举报