目录
List接口特有的常用方法
ArrayList
集合ArrayList 的构造方法
将 ArrayList 转换为线程安全的方法
LinkedList
LinkedList构造方法
ArrayList 和 Array 的区别
ArrayList 和 LinkedList 的区别
Vector
List接口特有的常用方法
List存储元素特点:有序可重复,且List集合中元素有下标(从0开始)
(1)void add(int index,E element) 在列表的指定位置插入指定元素
index索引即是该List中的下标,element为你插入的元素,如下图:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class List方法 {
public static void main(String[] args) {
List arr = new ArrayList();
arr.add("a");
arr.add("b");
arr.add("c");
//调用List中特有的add方法
arr.add(2,"java");
Iterator it = arr.iterator();
while (it.hasNext()){
Object ob = it.next();
System.out.println(ob);
}
}
}
结果图:
(2)E set(int index,E element) 用指定元素替换列表中指定位置的元素
import java.util.ArrayList;
import java.util.List;
public class List方法 {
public static void main(String[] args) {
List arr = new ArrayList();
arr.add("a");
arr.add("b");
arr.add("c");
arr.add("a");
System.out.println("初始的元素序列为:");
for( int i = 0 ; i < arr.size() ; i++){
Object obj = arr.get(i);
System.out.println(obj);
}
//替换指定位置下标的元素
arr.set(2,"java");
System.out.println("替换后后元素序列为:");
for( int i = 0 ; i < arr.size() ; i++){
Object obj = arr.get(i);
System.out.println(obj);
}
}
}
结果图:
(3)E get(int index) 返回列表中指定位置的元素
import java.util.ArrayList;
import java.util.List;
public class List方法 {
public static void main(String[] args) {
List arr = new ArrayList();
arr.add("a");
arr.add("b");
arr.add("c");
//调用List中特有的add方法
arr.add(2,"java");
for( int i =0 ; i< arr.size(); i++){
//调用get方法
Object obj = arr.get(i);
System.out.println(obj);
}
}
}
结果图:
(4) int indexOf(Object o) 返回列表中首次出现指定元素的索引,如果列表不包含此元素,则返回-1。
import java.util.ArrayList;
import java.util.List;
public class List方法 {
public static void main(String[] args) {
List arr = new ArrayList();
arr.add("a");
arr.add("b");
arr.add("c");
arr.add("a");
//获取 “a” 第一次出现时的索引
System.out.println(arr.indexOf("a"));
//获取 “a” 最后一次出现时的索引
System.out.println(arr.lastIndexOf("a"));
//如果没有指定元素时
System.out.println(arr.indexOf("java"));
}
}
结果图:
(5)E remove(int index) 移除列表中指定位置的元素
import java.util.ArrayList;
import java.util.List;
public class List方法 {
public static void main(String[] args) {
List arr = new ArrayList();
arr.add("a");
arr.add("b");
arr.add("c");
arr.add("a");
System.out.println("初始的元素序列为:");
for( int i = 0 ; i < arr.size() ; i++){
Object obj = arr.get(i);
System.out.println(obj);
}
//删除指定位置下标的元素
arr.remove(3);
System.out.println("删除后元素序列为:");
for( int i = 0 ; i < arr.size() ; i++){
Object obj = arr.get(i);
System.out.println(obj);
}
}
}
结果图:
ArrayList
(1)ArrayList 初始化容量为0,可以指定容量,未添加元素时为一个空数组,添加元素后默认容量由0 变为10
private static final int DEFAULT_CAPACITY = 10;
(2)集合底层是一个Object类型的数组
private static final Object[] EMPTY_ELEMENTDATA = {};
(3)会自动扩容1.5倍
先将旧容量右移1位,再加上旧容量就得到了新容量,正数右移1位相当于除以2,在该基础上加旧容量,则等价于新容量 = 旧容量 * 1.5,所以才有ArrayList每次扩容为旧容量的1.5倍的说法,最后调用Arrays.copyOf()方法进行拷贝,并将elementData指向新数组,而旧数组因为没有引用指向它,很快就会被垃圾收集器回收掉
private Object[] grow(int minCapacity) {
int oldCapacity = elementData.length;
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity,
oldCapacity >> 1 );
return elementData = Arrays.copyOf(elementData, newCapacity);
} else {
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}
集合ArrayList 的构造方法
ArrayList() 构造一个初始容量为十的空列表 ArrayList(int initialCapacity) 构造具有指定初始容量的空列表 ArrayList(Collection extends E> c) 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序
(1)无参构造
transient Object[] elementData;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
(2)指定容量ArrayList(int initialCapacity)
入参是ArrayList初始化容量,如果容量小于0就抛错,否则实例化一个Object对象数组赋值给全局变量elementData
public ArrayList(int initialCapacity) {
// 容量大于0,按照指定的容量初始化数组
if (initialCapacity > 0) {
// 创建一个数组,且指定长度为initialCapacity
this.elementData = new Object[initialCapacity];
// 如果initialCapacity容量为0,把EMPTY_ELEMENTDATA的地址赋值给elementData
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
// 容量小于0,抛非法异常
} else {
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
}
}
(3)指定集合ArrayList(Collection extends E> c)
传入Collection集合的对象,将传入的集合对象转为数组,然后给size赋值,判断如果传入的对象数组不是Object[],则转为Object[]
public ArrayList(Collection extends E> c) {
// 将给定的集合对象转成数组,且将数组的地址赋值给elementData
elementData = c.toArray();
// 将elementData的长度赋值给集合长度size,且判断是否不等于 0
if ((size = elementData.length) != 0) {
// 判断elementData 和 Object[] 是否为不一样的类型
// c.toArray()数组不是object数组进行转换成Object[]
// 每个集合的toarray()的实现方法不一样,所以需要判断一下,如果不是Object[].class类型,那么就需要使用ArrayList中的方法去改造一下。
// elementData.getClass()到底是什么类型的?
if (elementData.getClass() != Object[].class)
// 转换Object[]
// 如果不一样,使用Arrays的copyOf方法进行元素的拷贝
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// 给定的数组的长度为0,用空数组代替
this.elementData = EMPTY_ELEMENTDATA;
}
}
将 ArrayList 转换为线程安全的方法
Collections.synchronizedList()
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
public class ArrayListTest {
public static void main(String[] args) {
//默认容量为10,此时线程是不安全的
List list1 = new ArrayList();
//变成线程安全的方法
Collections.synchronizedList(list1);
list1.add(1);
list1.add(1);
list1.add(1);
list1.add(1);
}
}
LinkedList
(1)LinkedList 的底层是一个双向链表(包含两个指针的,pre指向前一个节点,next指向后一个节点,但是第一个节点head的pre指向null,最后一个节点的tail指向null)
注意:JDK1.6时为双向循环链表(第一个节点的pre指向最后一个节点,最后一个节点的next指向第一个节点,也形成一个“环”)而在JDK1.7以及往后版本,底层实现为双向链表
JDK1.8源码
public class LinkedList
extends AbstractSequentialList
implements List, Deque, Cloneable, java.io.Serializable
{
//长度
transient int size = 0;
//指向头结点
transient Node first;
//指向尾结点
transient Node last;
}
(2)元素在空间存储上的内存不连续,随机增删元素时,不会有大量元素移动,所以增删效率高,查找效率低
LinkedList构造方法
(1)无参构造(public LinkedList())
public LinkedList() {
}
(2)有参构造(public LinkedList(Collection extends E> c))
public LinkedList(Collection extends E> c) {
this();
addAll(c);
}
ArrayList 和 Array 的区别
Array
可以容纳基本类型和对象,而
ArrayList
只能容纳对象。
Array
是指定大小的,而
ArrayList
大小是固定
ArrayList 和 LinkedList 的区别
(1)ArrrayList
底层的数据结构是数组,支持随机访问,而
LinkedList
的底层数据结构是双向循环链表,不支持随机访问
(2)使用下标访问一个元素,
ArrayList
的时间复杂 度是 O(1)
,而
LinkedList
是
O(n)
Vector
(1)Vector 底层也是一个数组,初始化容量为10
(2)扩容后,容量为原容量的两倍
(3)Vector 中的所有方法都是线程同步的,线程是安全的
List存储元素特点:有序可重复,且List集合中元素有下标(从0开始)
(1)void add(int index,E element) 在列表的指定位置插入指定元素
index索引即是该List中的下标,element为你插入的元素,如下图:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class List方法 {
public static void main(String[] args) {
List arr = new ArrayList();
arr.add("a");
arr.add("b");
arr.add("c");
//调用List中特有的add方法
arr.add(2,"java");
Iterator it = arr.iterator();
while (it.hasNext()){
Object ob = it.next();
System.out.println(ob);
}
}
}
结果图:
(2)E set(int index,E element) 用指定元素替换列表中指定位置的元素
import java.util.ArrayList;
import java.util.List;
public class List方法 {
public static void main(String[] args) {
List arr = new ArrayList();
arr.add("a");
arr.add("b");
arr.add("c");
arr.add("a");
System.out.println("初始的元素序列为:");
for( int i = 0 ; i < arr.size() ; i++){
Object obj = arr.get(i);
System.out.println(obj);
}
//替换指定位置下标的元素
arr.set(2,"java");
System.out.println("替换后后元素序列为:");
for( int i = 0 ; i < arr.size() ; i++){
Object obj = arr.get(i);
System.out.println(obj);
}
}
}
结果图:
(3)E get(int index) 返回列表中指定位置的元素
import java.util.ArrayList;
import java.util.List;
public class List方法 {
public static void main(String[] args) {
List arr = new ArrayList();
arr.add("a");
arr.add("b");
arr.add("c");
//调用List中特有的add方法
arr.add(2,"java");
for( int i =0 ; i< arr.size(); i++){
//调用get方法
Object obj = arr.get(i);
System.out.println(obj);
}
}
}
结果图:
(4) int indexOf(Object o) 返回列表中首次出现指定元素的索引,如果列表不包含此元素,则返回-1。
import java.util.ArrayList;
import java.util.List;
public class List方法 {
public static void main(String[] args) {
List arr = new ArrayList();
arr.add("a");
arr.add("b");
arr.add("c");
arr.add("a");
//获取 “a” 第一次出现时的索引
System.out.println(arr.indexOf("a"));
//获取 “a” 最后一次出现时的索引
System.out.println(arr.lastIndexOf("a"));
//如果没有指定元素时
System.out.println(arr.indexOf("java"));
}
}
结果图:
(5)E remove(int index) 移除列表中指定位置的元素
import java.util.ArrayList;
import java.util.List;
public class List方法 {
public static void main(String[] args) {
List arr = new ArrayList();
arr.add("a");
arr.add("b");
arr.add("c");
arr.add("a");
System.out.println("初始的元素序列为:");
for( int i = 0 ; i < arr.size() ; i++){
Object obj = arr.get(i);
System.out.println(obj);
}
//删除指定位置下标的元素
arr.remove(3);
System.out.println("删除后元素序列为:");
for( int i = 0 ; i < arr.size() ; i++){
Object obj = arr.get(i);
System.out.println(obj);
}
}
}
结果图:
(1)ArrayList 初始化容量为0,可以指定容量,未添加元素时为一个空数组,添加元素后默认容量由0 变为10
private static final int DEFAULT_CAPACITY = 10;(2)集合底层是一个Object类型的数组
private static final Object[] EMPTY_ELEMENTDATA = {};(3)会自动扩容1.5倍
先将旧容量右移1位,再加上旧容量就得到了新容量,正数右移1位相当于除以2,在该基础上加旧容量,则等价于新容量 = 旧容量 * 1.5,所以才有ArrayList每次扩容为旧容量的1.5倍的说法,最后调用Arrays.copyOf()方法进行拷贝,并将elementData指向新数组,而旧数组因为没有引用指向它,很快就会被垃圾收集器回收掉
private Object[] grow(int minCapacity) { int oldCapacity = elementData.length; if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { int newCapacity = ArraysSupport.newLength(oldCapacity, minCapacity - oldCapacity, oldCapacity >> 1 ); return elementData = Arrays.copyOf(elementData, newCapacity); } else { return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)]; } }
集合ArrayList 的构造方法
ArrayList() 构造一个初始容量为十的空列表 ArrayList(int initialCapacity) 构造具有指定初始容量的空列表 ArrayList(Collection extends E> c) 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序
(1)无参构造
transient Object[] elementData;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
(2)指定容量ArrayList(int initialCapacity)
入参是ArrayList初始化容量,如果容量小于0就抛错,否则实例化一个Object对象数组赋值给全局变量elementData
public ArrayList(int initialCapacity) {
// 容量大于0,按照指定的容量初始化数组
if (initialCapacity > 0) {
// 创建一个数组,且指定长度为initialCapacity
this.elementData = new Object[initialCapacity];
// 如果initialCapacity容量为0,把EMPTY_ELEMENTDATA的地址赋值给elementData
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
// 容量小于0,抛非法异常
} else {
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
}
}
(3)指定集合ArrayList(Collection extends E> c)
传入Collection集合的对象,将传入的集合对象转为数组,然后给size赋值,判断如果传入的对象数组不是Object[],则转为Object[]
public ArrayList(Collection extends E> c) {
// 将给定的集合对象转成数组,且将数组的地址赋值给elementData
elementData = c.toArray();
// 将elementData的长度赋值给集合长度size,且判断是否不等于 0
if ((size = elementData.length) != 0) {
// 判断elementData 和 Object[] 是否为不一样的类型
// c.toArray()数组不是object数组进行转换成Object[]
// 每个集合的toarray()的实现方法不一样,所以需要判断一下,如果不是Object[].class类型,那么就需要使用ArrayList中的方法去改造一下。
// elementData.getClass()到底是什么类型的?
if (elementData.getClass() != Object[].class)
// 转换Object[]
// 如果不一样,使用Arrays的copyOf方法进行元素的拷贝
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// 给定的数组的长度为0,用空数组代替
this.elementData = EMPTY_ELEMENTDATA;
}
}
将 ArrayList 转换为线程安全的方法
Collections.synchronizedList()
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
public class ArrayListTest {
public static void main(String[] args) {
//默认容量为10,此时线程是不安全的
List list1 = new ArrayList();
//变成线程安全的方法
Collections.synchronizedList(list1);
list1.add(1);
list1.add(1);
list1.add(1);
list1.add(1);
}
}
LinkedList
(1)LinkedList 的底层是一个双向链表(包含两个指针的,pre指向前一个节点,next指向后一个节点,但是第一个节点head的pre指向null,最后一个节点的tail指向null)
注意:JDK1.6时为双向循环链表(第一个节点的pre指向最后一个节点,最后一个节点的next指向第一个节点,也形成一个“环”)而在JDK1.7以及往后版本,底层实现为双向链表
JDK1.8源码
public class LinkedList
extends AbstractSequentialList
implements List, Deque, Cloneable, java.io.Serializable
{
//长度
transient int size = 0;
//指向头结点
transient Node first;
//指向尾结点
transient Node last;
}
(2)元素在空间存储上的内存不连续,随机增删元素时,不会有大量元素移动,所以增删效率高,查找效率低
LinkedList构造方法
(1)无参构造(public LinkedList())
public LinkedList() {
}
(2)有参构造(public LinkedList(Collection extends E> c))
public LinkedList(Collection extends E> c) {
this();
addAll(c);
}
ArrayList 和 Array 的区别
Array
可以容纳基本类型和对象,而
ArrayList
只能容纳对象。
Array
是指定大小的,而
ArrayList
大小是固定
ArrayList 和 LinkedList 的区别
(1)ArrrayList
底层的数据结构是数组,支持随机访问,而
LinkedList
的底层数据结构是双向循环链表,不支持随机访问
(2)使用下标访问一个元素,
ArrayList
的时间复杂 度是 O(1)
,而
LinkedList
是
O(n)
Vector
(1)Vector 底层也是一个数组,初始化容量为10
(2)扩容后,容量为原容量的两倍
(3)Vector 中的所有方法都是线程同步的,线程是安全的
| ArrayList() | 构造一个初始容量为十的空列表 |
| ArrayList(int initialCapacity) | 构造具有指定初始容量的空列表 |
| ArrayList(Collection extends E> c) | 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序 |
(1)无参构造
transient Object[] elementData;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
(2)指定容量ArrayList(int initialCapacity)
入参是ArrayList初始化容量,如果容量小于0就抛错,否则实例化一个Object对象数组赋值给全局变量elementData
public ArrayList(int initialCapacity) {
// 容量大于0,按照指定的容量初始化数组
if (initialCapacity > 0) {
// 创建一个数组,且指定长度为initialCapacity
this.elementData = new Object[initialCapacity];
// 如果initialCapacity容量为0,把EMPTY_ELEMENTDATA的地址赋值给elementData
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
// 容量小于0,抛非法异常
} else {
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
}
}
(3)指定集合ArrayList(Collection extends E> c)
传入Collection集合的对象,将传入的集合对象转为数组,然后给size赋值,判断如果传入的对象数组不是Object[],则转为Object[]
public ArrayList(Collection extends E> c) {
// 将给定的集合对象转成数组,且将数组的地址赋值给elementData
elementData = c.toArray();
// 将elementData的长度赋值给集合长度size,且判断是否不等于 0
if ((size = elementData.length) != 0) {
// 判断elementData 和 Object[] 是否为不一样的类型
// c.toArray()数组不是object数组进行转换成Object[]
// 每个集合的toarray()的实现方法不一样,所以需要判断一下,如果不是Object[].class类型,那么就需要使用ArrayList中的方法去改造一下。
// elementData.getClass()到底是什么类型的?
if (elementData.getClass() != Object[].class)
// 转换Object[]
// 如果不一样,使用Arrays的copyOf方法进行元素的拷贝
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// 给定的数组的长度为0,用空数组代替
this.elementData = EMPTY_ELEMENTDATA;
}
}
Collections.synchronizedList()
import java.util.Collections; import java.util.List; import java.util.ArrayList; public class ArrayListTest { public static void main(String[] args) { //默认容量为10,此时线程是不安全的 List list1 = new ArrayList(); //变成线程安全的方法 Collections.synchronizedList(list1); list1.add(1); list1.add(1); list1.add(1); list1.add(1); } }
LinkedList
(1)LinkedList 的底层是一个双向链表(包含两个指针的,pre指向前一个节点,next指向后一个节点,但是第一个节点head的pre指向null,最后一个节点的tail指向null)
注意:JDK1.6时为双向循环链表(第一个节点的pre指向最后一个节点,最后一个节点的next指向第一个节点,也形成一个“环”)而在JDK1.7以及往后版本,底层实现为双向链表
JDK1.8源码
public class LinkedList
extends AbstractSequentialList
implements List, Deque, Cloneable, java.io.Serializable
{
//长度
transient int size = 0;
//指向头结点
transient Node first;
//指向尾结点
transient Node last;
}
(2)元素在空间存储上的内存不连续,随机增删元素时,不会有大量元素移动,所以增删效率高,查找效率低
LinkedList构造方法
(1)无参构造(public LinkedList())
public LinkedList() {
}
(2)有参构造(public LinkedList(Collection extends E> c))
public LinkedList(Collection extends E> c) {
this();
addAll(c);
}
ArrayList 和 Array 的区别
Array
可以容纳基本类型和对象,而
ArrayList
只能容纳对象。
Array
是指定大小的,而
ArrayList
大小是固定
ArrayList 和 LinkedList 的区别
(1)ArrrayList
底层的数据结构是数组,支持随机访问,而
LinkedList
的底层数据结构是双向循环链表,不支持随机访问
(2)使用下标访问一个元素,
ArrayList
的时间复杂 度是 O(1)
,而
LinkedList
是
O(n)
Vector
(1)Vector 底层也是一个数组,初始化容量为10
(2)扩容后,容量为原容量的两倍
(3)Vector 中的所有方法都是线程同步的,线程是安全的
(1)LinkedList 的底层是一个双向链表(包含两个指针的,pre指向前一个节点,next指向后一个节点,但是第一个节点head的pre指向null,最后一个节点的tail指向null)
注意:JDK1.6时为双向循环链表(第一个节点的pre指向最后一个节点,最后一个节点的next指向第一个节点,也形成一个“环”)而在JDK1.7以及往后版本,底层实现为双向链表
JDK1.8源码
public class LinkedListextends AbstractSequentialList implements List , Deque , Cloneable, java.io.Serializable { //长度 transient int size = 0; //指向头结点 transient Node first; //指向尾结点 transient Node last; }
(2)元素在空间存储上的内存不连续,随机增删元素时,不会有大量元素移动,所以增删效率高,查找效率低
(1)无参构造(public LinkedList())
public LinkedList() { }(2)有参构造(public LinkedList(Collection extends E> c))
public LinkedList(Collection extends E> c) { this(); addAll(c); }
ArrayList 和 Array 的区别
Array
可以容纳基本类型和对象,而
ArrayList
只能容纳对象。
Array
是指定大小的,而
ArrayList
大小是固定
ArrayList 和 LinkedList 的区别
(1)ArrrayList
底层的数据结构是数组,支持随机访问,而
LinkedList
的底层数据结构是双向循环链表,不支持随机访问
(2)使用下标访问一个元素,
ArrayList
的时间复杂 度是 O(1)
,而
LinkedList
是
O(n)
Vector
(1)Vector 底层也是一个数组,初始化容量为10
(2)扩容后,容量为原容量的两倍
(3)Vector 中的所有方法都是线程同步的,线程是安全的
(1)ArrrayList 底层的数据结构是数组,支持随机访问,而 LinkedList 的底层数据结构是双向循环链表,不支持随机访问 (2)使用下标访问一个元素, ArrayList 的时间复杂 度是 O(1) ,而 LinkedList 是 O(n)
Vector
(1)Vector 底层也是一个数组,初始化容量为10
(2)扩容后,容量为原容量的两倍
(3)Vector 中的所有方法都是线程同步的,线程是安全的
(1)Vector 底层也是一个数组,初始化容量为10
(2)扩容后,容量为原容量的两倍
(3)Vector 中的所有方法都是线程同步的,线程是安全的



