目录
1.List介绍
1.1 ArrayList集合
1.2 LinkedList
2.List常用方法
3.List的复制
在工作中,很多地方都会使用到List集合,可以说List是方便快捷的实现数据存储和返回的一种工具,但是在使用过程中不仅仅是简单的存储和读取,有时还是要考虑到List底层是如何去实现的,这样在遇见问题和优化时可以更轻松的去解决问题和修改或者调用方法.
Java中的集合主要分为两类,分别是Collection
体系和Map
体系,Map会在其他的文章中讲解,本片主要是对Collection体系中的List进行主要了解,而对Set和Queue进行顺带的一提.Collection主要有三个子接口,分别为List(列表)
、Set(集)
、Queue(队列)
。其中,List、Queue
中的元素有序可重复,而Set
中的元素无序不可重复。
List中主要有ArrayList
、LinkedList
两个实现类,在Collection中,List集合是有序的,可对其中每个元素的插入位置进行精确地控制,可以通过索引来访问元素,遍历元素。
当对List中元素进行循环遍历,修改其中的元素后,原list中的值会改变,当从数据库查询出User对象后,通过list对其进行循环修改,直接使用该list就好,不需要再创建新的集合.
该集合增删缓慢,但是改查便捷
1,ArrayList底层通过数组实现,随着元素的增加而动态扩容。
2,ArrayList是Java集合框架中使用最多的一个类,是一个数组队列,线程不安全集合。
它继承于AbstractList,实现了List, RandomAccess, Cloneable, Serializable接口。
1,ArrayList实现List,得到了List集合框架基础功能;
2,ArrayList实现RandomAccess,获得了快速随机访问存储元素的功能,RandomAccess是一个标记接口,没有任何方法;
3,ArrayList实现Cloneable,得到了clone()方法,可以实现克隆功能;
4,ArrayList实现Serializable,表示可以被序列化,通过序列化去传输,典型的应用就是hessian协议。
ArrayList集合的特点:
- 容量不固定,随着容量的增加而动态扩容(阈值基本不会达到)
- 有序集合(插入的顺序==输出的顺序)
- 插入的元素可以为null
- 改查效率更高(相对于LinkedList来说)
- 线程不安全
1,LinkedList
底层通过链表来实现,随着元素的增加不断向链表的后端增加节点。
2,LinkedList
是一个双向链表,每一个节点都拥有指向前后节点的引用。相比于ArrayList
来说,LinkedList
的随机访问效率更低。
它继承AbstractSequentialList,实现了List, Deque, Cloneable, Serializable接口。
通常对比ArrayList情况下,LinkedList增删比它效率高
1,LinkedList实现List,得到了List集合框架基础功能;
2,LinkedList实现Deque,Deque 是一个双向队列,也就是既可以先入先出,又可以先入后出,说简单点就是既可以在头部添加元素,也可以在尾部添加元素;
3,LinkedList实现Cloneable,得到了clone()方法,可以实现克隆功能;
4,LinkedList实现Serializable,表示可以被序列化,通过序列化去传输,典型的应用就是hessian协议。
A:添加功能
boolean add(E e):向集合中添加一个元素
void add(int index, E element):在指定位置添加元素
boolean addAll(Collection extends E> c):向集合中添加一个集合的元素。
B:删除功能
void clear():删除集合中的所有元素
E remove(int index):根据指定索引删除元素,并把删除的元素返回
boolean remove(Object o):从集合中删除指定的元素
boolean removeAll(Collection> c):从集合中删除一个指定的集合元素。
C:修改功能
E set(int index, E element):把指定索引位置的元素修改为指定的值,返回修改前的值。
D:获取功能
E get(int index):获取指定位置的元素
Iterator iterator():就是用来获取集合中每一个元素。
E:判断功能
boolean isEmpty():判断集合是否为空。
boolean contains(Object o):判断集合中是否存在指定的元素。
boolean containsAll(Collection> c):判断集合中是否存在指定的一个集合中的元素。
F:长度功能
int size():获取集合中的元素个数
G:把集合转换成数组
Object[] toArray():把集合变成数组。
有很多时候需要对获取到的数据进行拷贝,或者将List赋值给其他字段使用.这个就涉及到List底层是如何去生成和实现的问题了.
自 Java 9 开始,Jdk 里面为集合(List/ Set/ Map)都添加了 of 和 copyOf 方法,它们两个都用来创建不可变的集合,来看下它们的使用和区别。
例一:
List list = List.of("Java", "Python", "C");
List copy = List.copyOf(list);
System.out.println(list == copy); // true
例二:
List list = new ArrayList();
List copy = List.copyOf(list);
System.out.println(list == copy); // false
在这两个情况对比下我们就能看出,同样是使用of创建List集合,为什么会出现不同或者相同对象的结果.
问题出入源代码:
static List of(E... elements) {
switch (elements.length) { // implicit null check of elements
case 0:
return ImmutableCollections.emptyList();
case 1:
return new ImmutableCollections.List12<>(elements[0]);
case 2:
return new ImmutableCollections.List12<>(elements[0], elements[1]);
default:
return new ImmutableCollections.ListN<>(elements);
}
}
static List copyOf(Collection extends E> coll) {
return ImmutableCollections.listCopy(coll);
}
static List listCopy(Collection extends E> coll) {
if (coll instanceof AbstractImmutableList && coll.getClass() != SubList.class) {
return (List)coll;
} else {
return (List)List.of(coll.toArray());
}
}
可以看出 copyOf 方法会先判断来源集合是不是 AbstractImmutableList 类型,如果是,就直接返回,如果不是,则调用 of 创建一个新的集合。
在例1中,我们是通过of创建的一个集合,该集合是使用ImmutableCollections.List创建的集合,属于AbstractimmutableList的子类,所以在进行copyOf的时候直接将该集合返回了回去.
而例2中我们使用的是new ArrayList,所以在copyOf的时候就重新使用ImmutableCollections.List创建了一个List集合.
注意:使用of和copyOf创建的集合为不可变集合,不能进行添加、删除、替换、排序等操作,不然会报 java.lang.UnsupportedOperationException 异常。
上面演示了 List 的 of 和 copyOf 方法,Set 和 Map 接口都有。