- ArrayList 是基于数组实现的,是一个动态数组,容量支持自动自动增长
- ArrayList 线程不安全
- ArrayList 实现了 Serializable,支持序列化
- ** 元素对象不支持序列化。elementData 是被transient关键字修饰的,不可被序列化的,它自己实现了writeObject()和readObject()方法**
writeObject方法--序列化
readObject方法-- 反序列化
5、 elementData数组大小,大于等于列表的实际大小size。一个列表插入12个数据,数组整个长度15,实际大小size是12
6、列表默认elementData默认大小是10,new ArrayList<>()时初始化大小
7、 自动拓展容量,新容量=当前容量*1.5。参考第五点的例子,默认长度10的数组,插入12个数据后,数组长度变成了15。
8、看上图,最大容量是Integer.MAX_VALUE,但是默认会使用Integer.MAX_VALUE -8 。原因是为了减少出错的几率,注释上写了,因为虚拟机中,对象头里的markword classpointer需要占用内存。
9、 如果想将element对象大小弄成跟size一样大,也就是释放多余空闲的数组,使用trimToSize方法
实例效果:modCount增加了1次,elementData数组跟列表size一致
10、contains方法是通过indexOf实现
11、toArray的两种使用
(1)list.toArray();
(2)list.toArray(T[] a);
对于第一个重载方法,是将list直接转为Object[] 数组;
第二种方法是将list转化为你所需要类型的数组,当然我们用的时候会转化为与list内容相同的类型。
不明真像的同学喜欢用第一个,是这样写:
ArrayList<String> list=new ArrayList<String>();
for (int i = 0; i < 10; i++) {
list.add(""+i);
}
String[] array= (String[]) list.toArray();
结果一运行,报错:Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
原因一看就知道了,不能将Object[] 转化为String[],转化的话只能是取出每一个元素再转化。**java中的强制类型转换只是针对单个对象的,想要偷懒将整个数组转换成另外一种类型的数组是不行的,这和数组初始化时需要一个个来也是类似的。**像这样:
Object[] arr = list.toArray();
for (int i = 0; i < arr.length; i++) {
String e = (String) arr[i];
System.out.println(e);
}
所以第一个重构方法就不是那么好使了。
实际上,将list转化为array的时候,第二种重构方法更方便,用法如下:
String[] array =new String[list.size()];
list.toArray(array);
12、for循环的删除,为什么使用iterator,请看下文
developer.aliyun.com/article/403…
13、for循环的删除,为什么删除倒数第二个数据,不会抛异常CurrentModificationException,请看下文
14、Iterator 与 ListIterator 的同与异
相同点:
都是接口
相同的方法有hasNext , next , removre , forEachRemaining
不同点:
ListIterator 继承了Iterator
ListIterator 只可以用于List类型的集合
ListIterator多的方法有: hasPrevious, previous , nextIndex, previousIndex , set , add。 分为几类就是,可以双向遍历(hasPrevious, previous ),可以知道下标( nextIndex, previousIndex ),可以新增对象(add),可以修改(set)
add 是在当前位置的下一次插入一个数据, set是将当前位置是数据更换
15、subList返回的是原始List的一个视图,并没有新创建一个arrayList, 所以既不能将subList转回到ArrayList,在对subList或原始List变更时,也会引起联动变更,甚至错误。
原因看下图:subList里面的数据更改函数,会将自己的modCount同步原始List的modCount;但是原始List的add或remove函数,modCount不会同步给subList, 也就导致了subList会出现CurrentModificationException; 原始List的set函数只改了数据,为改变modCount,也就不会出错,此时原始List和subList的数据都改变了
16、spliterator ,另外一个迭代器。它有一个trySplit 函数,在可能并行的操作中使用。
如果我们调用trySplit一个分隔符,它将返回一个分隔符,其中包含调用方分隔符不会覆盖的元素。这就是说,我们用它将分离器分成多个部分。这样做的主要好处trySplit是我们可以并行处理分割的元素。trySplit如果源包含有限数量的元素,则重复调用将返回null
17、 ArrayList list = Arrays.asList("1“,”2”);很方便创建一个list对象,但是该list不能add,remove这些操作,因为此时返回list是AbstracList类的一个内部类,而不是真正的ArrayList。
而AbstractList只实现了add,set等函数,对set, add未实现
实际例子
18、JDK1.8新增方法,重写Collection接口的removeIf方法,为了安全和快速,removeIf分成两步走 :
1.根据匹配规则找到所有符合要求的元素
2.移除元素并转移剩余元素位置 *补充:
输出结果,将大于等于2的都删除了
[1,2,3]
after remove = [1]