- java泛型
E - Element (在集合中使用,因为集合中存放的是元素)
T - Type(Java 类)
K - Key(键)
V - Value(值)
N - Number(数值类型)
? - 表示不确定的java类型
Java源码中的Class代表这个类型所对应的类,而Class<?>表示类型不确定的类。
ArrayList提供了一个将List转为数组的一个非常方便的方法 list.toArray(),是将list直接转为Object[] 数组。
- Arrays.copyOf()
Array.copyOf() 用于复制指定的数组内容以达到扩容的目的,该方法对不同的基本数据类型都有对应的重载方法.
4. equals()方法
Object类的equals方法就是==,基本数据类型比较的是值是否相等,引用类型数据比较的是引用对象的内存地址是否一样。String类重写了equals方法,比较的是两个量的值是否相等。
- ArrayList与LinkedList、Vector对比区别
分析得出下面结论:
(1)ArrayList 本质上是一个可改变大小的数组.当元素加入时,其大小将会动态地增长.内部的元素可以直接通过get与set方法进行访问.元素顺序存储 ,随机访问很快,删除非头尾元素慢,新增元素慢而且费资源 ,较适用于无频繁增删的情况 ,比数组效率低,如果不是需要可变数组,可考虑使用数组 ,非线程安全.
(2)LinkedList 是一个双链表,在添加和删除元素时具有比ArrayList更好的性能.但在get与set方面弱于ArrayList. 适用于 :没有大规模的随机读取,有大量的增加/删除操作.随机访问很慢,增删操作很快,不耗费多余资源 ,允许null元素,非线程安全.
(3)Vector (类似于ArrayList)但其是同步的,开销就比ArrayList要大。如果你的程序本身是线程安全的,那么使用ArrayList是更好的选择。 Vector和ArrayList在更多元素添加进来时会请求更大的空间。Vector每次请求其大小的双倍空间,而ArrayList每次对size增长50%.
- ArrayList的扩容机制
ArrayList的扩容有两个位置
(1)使用无参构造创建集合,第一次添加元素时,会对集合进行判断,如果为空,则对添加元素所需的容量与默认容量进行比较,默认容量为10
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//当集合为空时
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
(2)添加元素时,容量不足时,会进行扩容。此为核心扩容机制
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void grow(int minCapacity) {
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);
}
// 创建一个新的数组,将旧数组copy进去
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
- batchRemove()方法详解
-
ArrayList中的序列化
序列化:将对象转化为字节的过程称为序列化过程。
反序列化:将字节转化为对象的过程称为反序列化。
序列化主要应用于网络传输和数据存储的场景。
有些时候,我们有这样的需求,某些属性不需要序列化。怎么做?使用transient关键字选择不需要序列化的字段。
使用transient虽然简单,但是将此属性完全隔离在了序列化之外。有没有一种机制,可以定制对象序列化的方式?通过重写writeObject与readObject方法,可以自己选择哪些属性需要序列化, 哪些属性不需要。如果writeObject使用某种规则序列化,则相应的readObject需要相反的规则反序列化,以便能正确反序列化出对象。
在new一个ArrayList对象时,默认是开辟一个长度为10的对象数组,如果只存入几个对象(不到默认的10个),如果采用默认序列化,则会将其余为null也序列化到文件中。
如果声明为transient类型,就能让虚拟机不会自行处理我们的这个数组,这才有了ArrayList的write/readObject方法。通过这种方式避免了浪费资源去存储没有的数据。重写完write/readObject方法后,ArrayList对象中只有不为null的元素才会序列化。