本人知识复盘系列的博客并非全部原创,大部分摘自网络,只是为了记录在自己的博客方便查阅,往后也会陆续在本篇博客更新本人查阅到的新的知识点,望悉知!
ArrayList
概述
ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。
ArrayList 继承了 AbstractList ,并实现了 List 接口。
创建实例:
import java.util.ArrayList; // 引入 ArrayList 类
ArrayList<E> objectName =new ArrayList<>(); // 初始化
基本的方法
增加:add()
访问:get()
删除:remove()
修改:set()
计算大小:size()
迭代数组列表:
for (int i = 0; i < sites.size(); i++) { System.out.println(sites.get(i)); }
for (String i : sites) { System.out.println(i); } // for-each方式
ArrayList 中的元素实际上是对象,在以上实例中,数组列表元素都是字符串 String 类型。
排序
用Collections类的sort()
更多ArrayList方法
add() | 将元素插入到指定位置的 arraylist 中 |
---|---|
addAll() | 添加集合中的所有元素到 arraylist 中 |
clear() | 删除 arraylist 中的所有元素 |
clone() | 复制一份 arraylist |
contains() | 判断元素是否在 arraylist |
get() | 通过索引值获取 arraylist 中的元素 |
indexOf() | 返回 arraylist 中元素的索引值 |
removeAll() | 删除存在于指定集合中的 arraylist 里的所有元素 |
remove() | 删除 arraylist 里的单个元素 |
size() | 返回 arraylist 里元素数量 |
isEmpty() | 判断 arraylist 是否为空 |
subList() | 截取部分 arraylist 的元素 |
set() | 替换 arraylist 中指定索引的元素 |
sort() | 对 arraylist 元素进行排序 |
toArray() | 将 arraylist 转换为数组 |
toString() | 将 arraylist 转换为字符串 |
ensureCapacity() | 设置指定容量大小的 arraylist |
lastIndexOf() | 返回指定元素在 arraylist 中最后一次出现的位置 |
retainAll() | 保留 arraylist 中在指定集合中也存在的那些元素 |
containsAll() | 查看 arraylist 是否包含指定集合中的所有元素 |
trimToSize() | 将 arraylist 中的容量调整为数组中的元素个数 |
removeRange() | 删除 arraylist 中指定索引之间存在的元素 |
replaceAll() | 将给定的操作内容替换掉数组中每一个元素 |
removeIf() | 删除所有满足特定条件的 arraylist 元素 |
forEach() | 遍历 arraylist 中每一个元素并执行特定操作 |
常见面试知识点
讲一讲ArrayList
ArrayList是底层使用动态数组实现的数据列表,但我们装在基本数据类型的时候,都是使用他们的包装类
查询效率高,增删效率低使用功率很高
说说ArrayList的默认长度
默认长度:10
1.7:创建的时候就会初始化数组的长度
1.8:当我们第一次向数组中添加数据的时候才会初始化数组,相当于懒加载
ArrayList和LinkedList的区别
ArrayList的底层使用动态数组,默认容量为10,当元素数量到达容量时,生成一个新的数组,大小为前一次的1.5倍,然后将原来的数组copy过来
因为数组有索引,所以ArrayList查找数据更快,但是添加数据效率更低
LinkedList的底层使用链表,在内存中是离散的,没有扩容机制;LinkedList在查找数据时需要从头遍历,所以查找慢,但是添加数据效率高
ArrayList的扩容
add()添加新数据的时候会进行一个判断,当我们添加的数据超过数组的长度时,数组就会进行扩容
这里分为两步:
1.先创建一个原数组长度1.5倍的新数组
1.7: 是原来数组的1.5倍 + 1
1.8: 使用位移运算符向右一位,效率要高很多
2.然后再把旧的数组copy到新的数组
说说ArrayList增删慢的原因
新增分为两种,一种是尾部新增,一种是指定位置的新增
指定位置的新增:
本质上也是copy一个数组,把指定位置之前的元素copy到新的数组,把指定位置之后的元素放在原index + 1 的位置
就是把index的位置挪出来,然后向指定位置添加元素
至于为什么说慢,如果数据量大的话,就需要一个一个的把数据移位,至于需要扩容了,就更慢了
删除的本质上也是copy一个数组:
先创建一个新的数组,长度为原数组的长度,再把要删除index位置之前的元素copy到新的数组,index之后的,放到新数组index-- 的位置
线程是否安全
不安全
我们一般只使用他的查询功能,如果涉及到频繁的增删或可以使用LinkedList
线程安全可以使用Vector,就是在每一个方法前都加上synchronized
ArrayList的遍历如何
ArrayList遍历最大的优势在于内存的连续性,CPU的内部缓存结构会缓存连续的内存片段,可以大幅降低读取内存的性能开销。
LinkedList
概述
链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址
链表可分为单向链表和双向链表:
一个单向链表包含两个值: 当前节点的值和一个指向下一个节点的链接
一个双向链表有三个整数值: 数值、向后的节点链接、向前的节点链接
与 ArrayList 相比,LinkedList 的增加和删除的操作效率更高,而查找和修改的操作效率较低
如图可得:
LinkedList 继承了 AbstractSequentialList 类
LinkedList 实现了 Queue 接口,可作为队列使用
LinkedList 实现了 List 接口,可进行列表的相关操作
LinkedList 实现了 Deque 接口,可作为队列使用
LinkedList 实现了 Cloneable 接口,可实现克隆
LinkedList 实现了 java.io.Serializable 接口,即可支持序列化,能通过序列化去传输
创建实例:
// 引入 LinkedList 类
import java.util.LinkedList;
LinkedList<E> list = new LinkedList<E>(); // 普通创建方法
或者
LinkedList<E> list = new LinkedList(Collection<? extends E> c); // 使用集合创建链表
基本方法
列表开头添加元素:addFirst()
列表结尾添加元素:addLast()
删除头部元素:removeFirst()
删除尾部元素:removeLast()
访问头部元素:getFirst()
访问尾部元素:getLast()
迭代和ArrayList差不多
更多方法
public boolean add(E e) | 链表末尾添加元素,返回是否成功,成功为 true,失败为 false。 |
---|---|
public void add(int index, E element) | 向指定位置插入元素。 |
public boolean addAll(Collection c) | 将一个集合的所有元素添加到链表后面,返回是否成功,成功为 true,失败为 false。 |
public boolean addAll(int index, Collection c) | 将一个集合的所有元素添加到链表的指定位置后面,返回是否成功,成功为 true,失败为 false。 |
public void addFirst(E e) | 元素添加到头部。 |
public void addLast(E e) | 元素添加到尾部。 |
public boolean offer(E e) | 向链表末尾添加元素,返回是否成功,成功为 true,失败为 false。 |
public boolean offerFirst(E e) | 头部插入元素,返回是否成功,成功为 true,失败为 false。 |
public boolean offerLast(E e) | 尾部插入元素,返回是否成功,成功为 true,失败为 false。 |
public void clear() | 清空链表。 |
public E removeFirst() | 删除并返回第一个元素。 |
public E removeLast() | 删除并返回最后一个元素。 |
public boolean remove(Object o) | 删除某一元素,返回是否成功,成功为 true,失败为 false。 |
public E remove(int index) | 删除指定位置的元素。 |
public E poll() | 删除并返回第一个元素。 |
public E remove() | 删除并返回第一个元素。 |
public boolean contains(Object o) | 判断是否含有某一元素。 |
public E get(int index) | 返回指定位置的元素。 |
public E getFirst() | 返回第一个元素。 |
public E getLast() | 返回最后一个元素。 |
public int indexOf(Object o) | 查找指定元素从前往后第一次出现的索引。 |
public int lastIndexOf(Object o) | 查找指定元素最后一次出现的索引。 |
public E peek() | 返回第一个元素。 |
public E element() | 返回第一个元素。 |
public E peekFirst() | 返回头部元素。 |
public E peekLast() | 返回尾部元素。 |
public E set(int index, E element) | 设置指定位置的元素。 |
public Object clone() | 克隆该列表。 |
public Iterator descendingIterator() | 返回倒序迭代器。 |
public int size() | 返回链表元素个数。 |
public ListIterator listIterator(int index) | 返回从指定位置开始到末尾的迭代器。 |
public Object[] toArray() | 返回一个由链表元素组成的数组。 |
public T[] toArray(T[] a) | 返回一个由链表元素转换类型而成的数组。 |
以下情况使用 ArrayList :
- 频繁访问列表中的某一个元素。
- 只需要在列表末尾进行添加和删除元素操作。
以下情况使用 LinkedList :
- 你需要通过循环迭代来访问列表中的某些元素。
- 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。
参考文章:
菜鸟教程