ArrayList是List接口的实现类,它是支持根据需要而动态增长的数组。java中标准数组是定长的,在数组被创建之后,它们不能被加长或缩短。这就意味着在创建数组时需要知道数组的所需长度,但有时我们需要动态程序中获取数组长度。ArrayList就是为此而生的。
因此,了解它的扩容机制对使用它尤为重要。
ArrayList扩容发生在add()方法调用的时候,下面是add()方法的源码:
public boolean add(E e) {
//扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
根据意思可以看出ensureCapacityInternal()是用来扩容的,形参为最小扩容量,进入此方法后:
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
通过方法calculateCapacity(elementData, minCapacity)获取:
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//如果传入的是个空数组则最小容量取默认容量与minCapacity之间的最大值
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
ensureExplicitCapacity方法可以判断是否需要扩容:
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 如果最小需要空间比elementData的内存空间要大,则需要扩容
if (minCapacity - elementData.length > 0)
//扩容
grow(minCapacity);
}
接下来重点来了,ArrayList扩容的关键方法grow():
private void grow(int minCapacity) {
// 获取到ArrayList中elementData数组的内存空间长度
int oldCapacity = elementData.length;
// 扩容至原来的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 再判断一下新数组的容量够不够,够了就直接使用这个长度创建新数组,
// 不够就将数组长度设置为需要的长度
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//若预设值大于默认的最大值检查是否溢出
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 调用Arrays.copyOf方法将elementData数组指向新的内存空间时newCapacity的连续空间
// 并将elementData的数据复制到新的内存空间
elementData = Arrays.copyOf(elementData, newCapacity);
}
从此方法中我们可以清晰的看出其实ArrayList扩容的本质就是计算出新的扩容数组的size后实例化,并将原有数组内容复制到新数组中去。
到此扩容就基本完成了。
本文向大家介绍windows消息机制知道吗,请说一说相关面试题,主要包含被问及windows消息机制知道吗,请说一说时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 当用户有操作(鼠标,键盘等)时,系统会将这些时间转化为消息。每个打开的进程系统都为其维护了一个消息队列,系统会将这些消息放到进程的消息队列中,而应用程序会循环从消息队列中取出来消息,完成对应的操作。
本文向大家介绍说一下 hibernate 的缓存机制?相关面试题,主要包含被问及说一下 hibernate 的缓存机制?时的应答技巧和注意事项,需要的朋友参考一下 hibernate 常用的缓存有一级缓存和二级缓存: 一级缓存:也叫 Session 缓存,只在 Session 作用范围内有效,不需要用户干涉,由 hibernate 自身维护,可以通过:evict(object)清除 object
本文向大家介绍说一下 zookeeper 的通知机制?相关面试题,主要包含被问及说一下 zookeeper 的通知机制?时的应答技巧和注意事项,需要的朋友参考一下 客户端端会对某个 znode 建立一个 watcher 事件,当该 znode 发生变化时,这些客户端会收到 zookeeper 的通知,然后客户端可以根据 znode 变化来做出业务上的改变。
1. Android端SDK为什么要使用多进程来实现? Android端运行时SDK采用多进程机制实现,所谓多进程是指小程序与宿主App分隔开,各自运行在独立的进程中,进程之间互不干扰,通过跨进程通信相互传递数据。之所以选用多进程,原因主要有以下几点: 不占用宿主App的内存。系统会为小程序进程分独立的内存空间,小程序不会占用主进程的内存,因此App不用担心内存溢出等问题; 保证宿主App安全稳定
本文向大家介绍请你说一说C++多线程的同步,锁的机制?相关面试题,主要包含被问及请你说一说C++多线程的同步,锁的机制?时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 同步的时候用一个互斥量,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁。对互斥量进行加锁以后,任何其他试图再次对互斥量加锁的线程将会被阻塞直到当前线程释放该互斥锁。如果释放互斥锁时有多个线程阻塞,所有在该互斥
本文向大家介绍请你来说一说Redis的定时机制怎么实现的相关面试题,主要包含被问及请你来说一说Redis的定时机制怎么实现的时的应答技巧和注意事项,需要的朋友参考一下 参考回答: Redis服务器是一个事件驱动程序,服务器需要处理以下两类事件:文件事件(服务器对套接字操作的抽象)和时间事件(服务器对定时操作的抽象)。Redis的定时机制就是借助时间事件实现的。 一个时间事件主要由以下三个属性组成: