List
特点
有序:有序(元素存入集合的顺序和取出的顺序一致)。List 中每个元素都有索引标记。 可以根据元素的索引标记(在 List 中的位置)访问元素,从而精确控制这些元素。 可重复:List 允许加入重复的元素。更确切地讲,List 通常允许满足e1.equals(e2) 的元素重复加入容器
常用实现类
ArrayList类
特点
底层由数组实现,存储的数据具有有序性,重复性,且查询效率高,增删效率低,线程不安全,JDK1.8后使用了延迟加载,只有添加元素是才创建数组,扩容的大小为原来的1.5倍题
有序性:由于底层是由数组实现的,所以ArrayList将需要保存的数据依次保存在数组中。 重复性:可以保存重复的数据即e1.equals(e2) 的数据。 查询效率高:因为底层由数组实现并且是按顺序将数据存入数组中,所以我们可以通过数组的下标进行数据索引,而无需进行遍历查找。 增删效率低:数组的性质决定了ArrayList的增删效率低,因为数组是一串连续的内存空间进行数据保存,如果对数组中的元素进行增删操作的话,除非是数组头尾元素,否则将要对数组中某些元素的位置造成变化,增加了时间开销。
常用方法
public boolean add(E,e): 向集合当中添加元素,参数的类型和泛型保持一致,返回值代表是否成功(true、false) public E get(int index):从集合当中获取元素,参数是索引编号,返回值就是对应位置的元素 public E remove(int index):从集合当中删除元素,参数是索引编号,返回值就是被删除的元素 public int size():获取集合的尺寸长度,返回值是集合中包含的元素个数 注意事项: *对于arraylist集合来说,add添加动作一定成功,所以返回值可用可不用 ,但对于其他集合来说,add添加动作不一定成功
代码示例
public class Demo {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
boolean csdn = arrayList.add("csdn");
System.out.println("打印添加的元素是否成功: "+csdn);
arrayList.add("csdn1");
arrayList.add("csdn2");
arrayList.add("csdn3");
arrayList.add("csdn1");
arrayList.add("csdn4");
arrayList.add("csdn5");
String s0 = arrayList.get(0);
System.out.println("ArrayList集合位置为0的元素为: "+s0);
int csdnIndex = arrayList.indexOf("csdn");
System.out.println("元素csdn所在位置为: "+csdnIndex);
int csdn1 = arrayList.lastIndexOf("csdn1");
System.out.println("元素csdn1最后所在位置为: "+csdn1);
System.out.println("删除前的集合: "+arrayList);
boolean csdn2 = arrayList.remove("csdn2");
String remove = arrayList.remove(2);
System.out.println("csdn2是否删除成功: "+csdn2);
System.out.println("集合中位置为2的被删除的元素为: "+remove);
System.out.println("删除后的集合: "+arrayList);
boolean empty = arrayList.isEmpty();
System.out.println("当前集合是否为空:"+empty);
int size = arrayList.size();
System.out.println("当前集合大小为: "+size);
System.out.println("替换前集合位置3的元素为: "+arrayList.get(3));
String th3 = arrayList.set(3, "tihuan3");
System.out.println(th3+"替换后的集合为:"+arrayList);
boolean csdn5 = arrayList.contains("csdn5");
System.out.println("当前集合是否包含元素csdn5: "+ csdn5);
}
}
打印结果:
打印添加的元素是否成功: true
ArrayList集合位置为0的元素为: csdn
元素csdn所在位置为: 0
元素csdn1最后所在位置为: 4
删除前的集合: [csdn, csdn1, csdn2, csdn3, csdn1, csdn4, csdn5]
csdn2是否删除成功: true
集合中位置为2的被删除的元素为: csdn3
删除后的集合: [csdn, csdn1, csdn1, csdn4, csdn5]
当前集合是否为空:false
当前集合大小为: 5
替换前集合位置3的元素为: csdn4
csdn4替换后的集合为:[csdn, csdn1, csdn1, tihuan3, csdn5]
当前集合是否包含元素csdn5: true
ArrayList底层源码分析
add()方法: 从添加元素方法可以看出ArrayList底层由数组实现。 添加元素自动扩容源代码实现:
剩下的相关方法源码,小伙伴们感兴趣可以去看一下!
LinkedList类
特点
底层由双向链表实现,满足List类的有序性和可重复性,特点是查询速度慢(需要遍历查询),增删效率高(只需要修改前后两个节点),线程不安全。
有序性:LinkedList类通过链表来保证存储元素的有序性。 可重复性:并未对存储的元素做出限制,所以可以存储重复的元素。 查询速度慢:因为链表无法通过索引进行数据查询,所以需要遍历链表查询元素。 增删效率高:由于链表是通过一个个节点连接起来的,所以增删操作只需要操作前后两个节点即可。
常用方法
与ArrayList类一致。
ArrayList类与LinkedList类的区别
1、ArrayList 是基于数组实现的,LinkedList 是基于双向链表实现的,ArrayList 在新增和删除元素时,因为涉及到数组复制,所以效率比 LinkedList 低,而在遍历的时候,ArrayList 的效率要高LinkedList。 2、ArrayList 是基于动态数组实现的非线程安全的集合。当底层数组满的情况下还在继续添加的元素时,ArrayList则会执行扩容机制扩大其数组长度。ArrayList查询速度非常快,使得它在实际开发中被广泛使用。美中不足的是插入和删除元素较慢,同时它并不是线程安全的。 扩容机制:通过扩容机制判断原数组是否还有空间,若没有则重新实例化一个空间更大的新数组,把旧数组的数据拷贝到新数组中,先判断下标是否越界,再扩容。若插入的下标为i,则通过复制数组的方式将i后面的所有元素,往后移一位,新数据替换下标为i的旧元素。 LinkedList 是基于双向链表实现的非线程安全的集合,它是一个链表结构,不能像数组一样随机访问,必须是每个元素依次遍历直到找到元素为止。其结构的特殊性导致它查询数据慢。查询时先判断元素是靠近头部,还是靠近尾部,然后再查询。
Vector类(不常用)
特点
Vector 底层是用数组实现的,相关的方法都加了同步检查,因此“线程安全,效率低”。没有延时加载,一旦初始化后立即创建数组,数组长度为10,扩容大小为原来的2倍。
常用的实现List类线程安全的三种方法
1、Vector类:相关的方法都加了同步检查,因此“线程安全,效率低”。没有延时加载,一旦初始化后立即创建数组,数组长度为10,扩容大小为原来的2倍。 2、使用Collections的静态方法synchronizedList(List< T> list):使用这种方法可以获得线程安全的List容器,它和Vector的区别在于它采用了同步代码块实现线程间的同步。 3、采用CopyOnWriteArrayList容器:在写操作的时候复制数组,为了将读取的性能发挥到极致,在该类的使用过程中,读读操作和读写操作都不互斥。
|