ArrayList简介
ArrayList 是一个数组队列,相当于 动态数组。与Java中的数组相比,它的容量能动态增长。它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。
ArrayList 继承了AbstractList,实现了List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。ArrayList 实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在ArrayList中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。稍后,我们会比较List的“快速随机访问”和“通过Iterator迭代器访问”的效率。
ArrayList 实现了Cloneable接口,即覆盖了函数clone(),能被克隆。
ArrayList 实现java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输。

和Vector不同,ArrayList中的操作不是线程安全的!所以,建议在单线程中才使用ArrayList,而在多线程中可以选择Vector或者CopyOnWriteArrayList。



ArrayList 的底层是数组队列,相当于动态数组。与 Java 中的数组相比,它的容量能动态增长。在添加大量元素前,应用程序可以使用ensureCapacity操作来增加 ArrayList 实例的容量。这可以减少递增式再分配的数量。 它继承于 AbstractList,实现了 List, RandomAccess, Cloneable, java.io.Serializable 这些接口。 在我们学数据结构的时候就知道了线性表的顺序存储,插入删除元素的时间复杂度为O(n),求表长以及增加元素,取第 i 元素的时间复杂度为O(1)

底层使用数组保存所有元素,默认情况下初始化空数组(长度为0的数组),通过指定数组来初始容量:

1. 当指定的初始容量大于0,初始化指定大小的数组
2. 当指定的初始容量等于0,初始化空数组
3. 当指定的初始容量小于0,抛出IllegalArgumentException异常

长度超过10以后,进行扩容,扩容是原来长度的1.5倍.通过调用add()或者addAll()方法触发


ArrayList智能存储对象,不能存储基本数据类型,所以泛型不能写基础数据类型

ArrayList 继承了AbstractList,实现了List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。
ArrayList 实现了RandomAccess 接口, RandomAccess 是一个标志接口,表明实现这个这个接口的 List 集合是支持快速随机访问的。在 ArrayList 中,我们即可以通过元素的序号快速获取元素对象,这就是快速随机访问。
ArrayList 实现了Cloneable 接口,即覆盖了函数 clone(),能被克隆。
ArrayList 实现java.io.Serializable 接口,这意味着ArrayList支持序列化,能通过序列化去传输。
和 Vector 不同,ArrayList 中的操作不是线程安全的!所以,建议在单线程中才使用 ArrayList,而在多线程中可以选择 Vector 或者 CopyOnWriteArrayList。

1.API ,核心源码,遍历方式,toArray异常


参考:

https://www.yuque.com/docs/share/522a0586-2a58-4649-8ae0-47468bba7e3a?#


2.System.arraycopy()和Arrays.copyOf()方法区别


Arrays.copyOf()会返回一个新数组。该新数组在方法内部被创建

System.arraycopy()需要预先创建好一个目标数组,且不会返回任何值(将原数组拷贝到你自己定义的数组里面,而且可以选择拷贝的起点和长度以及放入新数组中的位置)。比如当希望数据的操作在原数组中进行时,只需将原数组作为目标数组即可。

Arrays.copyOf()实际上是调用了System.arraycopy()

System.arraycopy() 在拷贝数组的时候,采用的使用浅复制,复制结果是一维的引用变量传递给副本的一维数组,修改副本时,会影响原来的数组,System.arraycopy()也是线程不安全的.
关于性能问题,当测试数组的范围比较小的时候,两者相差的时间无几,当测试数组的长度达到百万级别,System.arraycopy的速度优势就开始体现了,根据对底层的理解,System.arraycopy是对内存直接进行复制,减少了for循环过程中的寻址时间,从而提高了效能。

在看ArrayList源码时看见,当扩容时采取的是Arrays.copyOf(),插入或删除时使用的是System.arrayCopy()方法. add(int index, E element)方法就很巧妙的用到了arraycopy()方法让数组自己复制自己实现让index开始之后的所有成员后移一个位置

详细:

https://www.yuque.com/docs/share/9daeba8c-c851-48a3-bf8d-7755aa2b578d?#


3.jdk8扩容技术


当ArrayList不为空时,并且它的大小不超过10时,它的容量都是10.但当大小从10增加到11时,容量变成了15,扩大了1.5倍.
也有人说jdk1.6版本以后,ArrayList扩容后的容量为1.5倍加1.

扩容原理参考下面的:
https://www.yuque.com/docs/share/6a9f492e-e587-4c0f-a1e9-95db6d2be359


4.内部类

(1)private class Itr implements Iterator
(2)private class ListItr extends Itr implements ListIterator
(3)private class SubList extends AbstractList implements RandomAccess
(4)static final class ArrayListSpliterator implements Spliterator

 ArrayList有四个内部类,其中的Itr是实现了Iterator接口,同时重写了里面的hasNext(),next(),remove()等方法;其中的ListItr继承Itr,实现了ListIterator接口,同时重写了hasPrevious(),nextIndex(),previousIndex(),previous(),set(E e),add(E e)等方法,所以这也可以看出了 Iterator和ListIterator的区别:ListIterator在Iterator的基础上增加了添加对象,修改对象,逆向遍历等方法,这些是Iterator不能实现的。

5.循环遍历添加值都是最后一次的值

从网上找个答案,结果是当添加值的时候并不是添加实体类,而是实体类的引用,相当于指针,存储的也是存储的指针,所以我添加的都是最后一次的引用,这个引用没有变化,所以最后arraylist中的数据指向都是最后一次封装的值,所以当往ArrayList循环添加数据的时候需要重新new对象.

ArrayList resultList = new ArrayList<>();for (int i = 0; i < yearList.size(); i++) {
HashMap DateMap = new HashMap<>();//每次循环的时候都需要new对象

String creationTimeYear = (String) yearList.get(i).get(“creationTimeYear”);//每次循环的日期中的年

DateMap.put(“year”, creationTimeYear);//组装年数据

map.put(“year”, creationTimeYear);

//通过起始地址和结束地址和年查询月份集合
String[] monthArray = this.appUserOrderDao.selectMonthDataByStartAddressAndEndAddress(map);

DateMap.put(“month”, monthArray);

map.put(“year”, creationTimeYear);//每次循环的日期中的年
resultList.add(DateMap);

}


6.利用set集合去根据map的指定key去重复


/cityList的数据:
{“status”:1,”message”:”请求成功”,
“data”:[
{“city1”:”台北市”,”longitude1”:121.520076,”latitude1”:25.030724},
{“city1”:”金门县”,”longitude1”:118.32277,”latitude1”:24.42931},
{“city1”:”台北市”,”longitude1”:121.541766,”latitude1”:25.074708},
{“city1”:”金门县”,”longitude1”:118.326118,”latitude1”:24.430389}
]}
/
List> cityList = this.appUserOrderDao.selectCity(map);
//对结果去重复
HashSet citySet = new HashSet<>();
List> resultMapList = new ArrayList<>();
for (Map cityMap : cityList) {
if (citySet.add(cityMap.get(“city1”))) { //如果重复了就添加失败就返回了false,否则就返回了true
resultMapList.add(cityMap);
}
}

return JsonUtils.objectToJson(new JsonResult(resultMapList));

结果:
{
“status”: 1,
“message”: “请求成功”,
“data”: [
{
“city1”: “台北市”,
“longitude1”: 121.520076,
“latitude1”: 25.030724
},
{
“city1”: “金门县”,
“longitude1”: 118.32277,
“latitude1”: 24.42931
}
]
}


7.根据集合里面对象的某一个成员属性去重复


比如根据集合里面的对象的id进行去重复,

waterMenus 是一个List集合,泛型是 waterMenu


List waterMenuList = waterMenus.stream().collect(
Collectors.collectingAndThen(Collectors.toCollection(
() -> new TreeSet<>(Comparator.comparing(o -> o.getId()))), ArrayList::new));


8.list集合去重复

list集合去重复
List yearList = this.appUserOrderDao.selectTimeListYear(map);
//list集合去重复
yearList = (List) yearList.stream().distinct().collect(Collectors.toList());

(二)解决方案

1.集合判空


import org.springframework.util.CollectionUtils

ArrayList objects = new ArrayList<>();
System.out.println(CollectionUtils.isEmpty(objects));


org.springframework.util.ObjectUtils
ArrayList arrayList = new ArrayList() ;
boolean empty = ObjectUtils.isEmpty(arrayList);

2.合并数组到指定的集合里面

import org.springframework.util.CollectionUtils

String[] a = new String[]{“a”, “b”};
ArrayList strings = new ArrayList<>();
strings.add(“aa”);
strings.add(“bb”);
CollectionUtils.mergeArrayIntoCollection(a, strings);

3.查询这个集合里面的数据是否在别的集合里面存在

import org.springframework.util.CollectionUtils


List integers1 = Arrays.asList(1, 2, 3, 4, 5);
ArrayList integers = new ArrayList<>(integers1);
ArrayList a = new ArrayList<>(integers1);

ArrayList integers2 = new ArrayList<>(Arrays.asList(1, 25, 154, 112));
boolean b = CollectionUtils.containsAny(integers, a);//true
boolean b1 = CollectionUtils.containsAny(integers1, integers2); //true

4.检查元素在指定的集合是否存在

import org.springframework.util.CollectionUtils

List integers1 = Arrays.asList(1, 2, 3, 4, 5);
ArrayList integers = new ArrayList<>(integers1);
boolean b = CollectionUtils.containsInstance(integers, 1);//true
boolean b1 = CollectionUtils.containsInstance(integers, 10);//false

5.在两个集合里面检索第一个重复的值


import org.springframework.util.CollectionUtils

//两个集合第一个重复的值是55 ,所以就返回 55
ArrayList aa = new ArrayList<>(Arrays.asList(1, 55, 3, 4, 5));
ArrayList bb = new ArrayList<>(Arrays.asList(11, 55, 3, 66, 165));

Integer firstMatch = CollectionUtils.findFirstMatch(aa, bb); // 55
//两个集合第一个重复的值是1 , 所以就返回 1
Integer b = CollectionUtils.findFirstMatch(new ArrayList<>(Arrays.asList(1, 55, 3, 4, 5)), aa);//1

(三)Collections工具类


Collections工具类
该工具类提供了大量针对Collection/Map的操作,总体可分为四类,都为静态(staic)方法:
1、排序操作(主要针对List接口相关)
reverse(List list):反转指定List集合中元素的顺序
shuffle(List list):对List中的元素进行随机排序(洗牌)
sort(List list):对List里的元素根据自然升序排序
sort(List list,Comparator c):自定义比较器进行排序
swap(List list,int i,int j):将指定List集合中i 处元素和j 处元素进行交换
rotate(List list,int distance):将所有元素向右移位指定长度,如果distance等于size那么结果不变
2、查找和替换(主要针对Collection接口相关)
binarySearch(List list,Object key):使用二分法查找,以获得指定对象在List中的索引,前提是集合已经排序
max(Collection coll):返回最大元素
max(Collection coll,Comparator comp):根据自定义比较器,返回最大元素
min(Collection] coll):返回最小元素
min(Collection coll,Comparator comp):根据自定义比较器,返回最小元素
fill(List list,Object obj):使用指定对象填充
frequency(Collection Object obj):返回指定集合中指定对象出现的次数
replaceAll(List list,Object old,Object new):替换
int frequency(Collection c, Object o)//统计元素出现次数
int indexOfSubList(List list, List target)//统计target在list中第一次出现的索引,找不到则返回-1,类比int lastIndexOfSubList(List source, list target).


3、同步控制(不要用,效率低,直接用juc包下的并发集合)


4、设置不可变得结合
Collections工具类有三种方法返回一个不可变集合
emptyXxx(): 返回一个空的不可变的集合对象
singletonXxx(): 返回一个只包含指定对象的,不可变的集合对象
unmodifiableXxx(): 返回指定集合对象的不可变视图
5、其它
disjoint(Collections<?>c1,Collections<?>c2) 如果两个指定collection中没有相同的元素,则返回true
addAll(Collection<?super T>c,T…a) 一种方便的方式,将所有指定元素添加到指定collection中
ComparatorreverseOrder(Comparatorcmp)返回一个比较器,它强行反转指定比较器的顺序。如果指定比较器为null,则
此方法等同于reverseOrder(){返回一个比较器,它对实现 Comparable接口的对象集合施加了 自然排序的相反}


参考:
https://www.yuque.com/docs/share/2a13c89a-1028-408f-bea7-8e19dcf2d82d?#

(四)Arrays工具类


1. 排序 : sort()
2. 查找 : binarySearch()
3. 比较: equals()
4. 填充 : fill()
5. 转列表: asList()
6. 转字符串 : toString()
7. 复制: copyOf()

具体代码看这里:

ArrayList笔记 - 图1