|----Collection<T> 接口:单列集合,用来储存一个一个对象
|----List<T> 接口:储存有序,可重复的数据。动态数组
(1)ArrayList<T> List接口的主要实现类,无特殊要求,都会使用它。(线程不安全的,执行效率高,底层使用Object[] 存储数据)。在JDK8以前,当实例化一个ArrayList后,它里边就会创建一个长度为10的Object[],但是在JDK8以后,实例化一个ArrayList后会把底层的Object[]赋值为{},只有当第一次去执行add()操作时才会初始化Object[]的长度,默认是10,当然也可以在初始化的时候指定。它的扩容方式是原来长度的1.5倍。
(2)LinkedList 底层使用双向链表结构存储数据,线程不安全的。底层不存在扩容的说法。
(3)Vector List接口的最早的实现类。 (线程安全的,执行效率低。很多方法加了synchronize关键字,底层使用Object[] 存储数据)如果没有在初始化的时候指定要增加的长度的话,那就扩容为原来数组的2。
三者对比。
第一,ArrayList和Vector底层使用的都是数组,而LinkedList底层使用的是双向链表(Node<E>维护了指向前一个节点和后一个节点的Node<E>)。这是底层用的数据结构不同。
第二,ArrayList和Vector要节省内存一点,与LinkedList。因为LinkedList还需要维护两个指向前一个节点和后一个节点的Node。这是从占用内存的角度来看。
第三,ArrayList因为底层使用的是数组,所以它在数据插入(任意位置),删除都会将之后的元素全部改变位置,数组长度很长时,效率贼低。但是它在查询,修改这方面效率就比较高了,可以直接通过数组下标来操作。LinkedList则刚好相反,因为它底层使用的是双向链表,所以在数据插入,删除只需要改变前一个节点的引用就可以了,但是它的查询很慢(最差情况下)。因为它要一个节点一个节点的查询下去。这是从操作效率的角度来看。
第四,ArrayList和LinkedList是线程不安全的(底层方法没有用synchronized关键字声明),而Vector是线程安全的(线程不安全可能会出现一些问题,多个线程同时操作一个ArrayList对象,数据不安全,一个线程刚给第i位赋值,另一个线程又在第i位插入。还可能导致现在的ArrayList的底层数组越界,在还没来得及扩容的情况下)。这是从线程安全的角度来看(但是在Collections这个工具类里提供了将集合从线程安全转换成线程安全的方法)。
第五,ArrayList当容量满了之后,扩容成原来长度的1.5。而Vector如果没有在初始化的时候指定要增加的长度的话,那就扩容为原来数组的2。下边是源码里扩容的方式截图。
常见方法的使用
@Test
public void Test1(){
List<Integer> integers = new ArrayList<>() ;
integers.add(12);
System.out.println(8>>2);
List<Integer> list = new ArrayList<>();
list.add(12);
list.add(13);
list.add(12);
list.add(14);
list.add(15);
list.add(12);
list.add(17);
// 在指定游标插入数据
list.add(1,78);
// 在指定位置插入一个集合
list.addAll(2,list);
System.out.println(list);
// 查找集合中是否存在某个元素
System.out.println("list.indexOf(45) = " + list.indexOf(12));
System.out.println("list.lastIndexOf(12) = " + list.lastIndexOf(12));
// 删除某个元素,可以指定下标删除
System.out.println("list.remove(6) = " + list.remove(6));
System.out.println(list);
System.out.println("list.remove((Integer)12) = " + list.remove((Integer) 12));
System.out.println(list);
System.out.println("list.remove(12) = " + list.removeAll(integers));
System.out.println(list);
Object[] objects = list.toArray();
Arrays.sort(objects);
Arrays.toString(objects);
}
/**
*LinkedList在堆集合中的数据进行增加,删除,插入的效率要优于ArrayList。因为底层使用的是双向 链表储存结构
*
* 但是在查找,修改原数据的效率上
*
*@Author 胡川
*@Date 2021/5/29 15:49
*/
@Test
public void Test2(){
List<String> list = new LinkedList<String>();
list.add("45");
list.add("Tom");
list.add("cd");
list.add("sd");
list.add("fr");
// 获取迭代器后不能对集合进行添加,删除操作了,不然会报错
Iterator<String> iterator = list.iterator();
System.out.println("list = "+list);
// 需要注意的是,集合中的subList()只是对集合的数据部分的视图,当修改原集合,再对截取的集 合做任何操作都会报错
List<String> list1 = list.subList(0, 3);
System.out.println("list1 = "+list1);
// list.add("99");
System.out.println("list = "+list);
// System.out.println("list1 = " + list1);
while (iterator.hasNext())
System.out.println("iterator.next() = " + iterator.next());
System.out.println("list.get(2) = " + list.get(2));
System.out.println("list.set(2,\"uiyggahha\") = " + list.set(2, "uiyggahha"));
System.out.println("2>>1 = " + (4 << 1));
}
/**
*ArrayList<T> 常用方法使用
*/
@Test
public void Test3(){
// 声明集合底层数组长度为15
List<Integer> integerList2 = new ArrayList<>(15);
integerList2.add(99);
integerList2.add(99);
integerList2.add(99);
integerList2.add(99);
// 声明集合底层数组长度为15
List<Integer> integerList = new ArrayList<>(15);
integerList.add(45);
integerList.add(75);
integerList.add(65);
integerList.add(84);
integerList.add(98);
// 因为add()的是一个对象,所以可以添加null,也会算在size()里
integerList.add(null);
integerList.add(null);
integerList.add(84);
integerList.add(65);
System.out.println("integerList = " + integerList);
// 将索引为2的位置的元素向后移,原先的位置插入元素element
integerList.add(2,45);
System.out.println("在原先的集合第2位插入元素45" + integerList);
// 在集合的最后添加一个集合
integerList.addAll(integerList2);
System.out.println("在原先的集合后插入另一个集合 " + integerList);
// 在集合的索引处添加另一个集合的所有元素
integerList.addAll(4,integerList2);
System.out.println("在原先的集合第4位插入另一个集合 " + integerList);
// 删除集合中索引为45的位置的元素,
// 因为这个集合是Integer类型的,所以这个remove()调用的是List接口的父接口的remove(int index)方法
integerList.remove(5);
System.out.println("删除第5位的元素 " + integerList);
// 删除集合中元素值为45的第一个元素,
// 因为remove()中指定了45是Integer类型,所以调用的是实现List接口的子类对象的remove(Object o)方法
integerList.remove((Integer) 45);
System.out.println("删除第一个元素值为45的元素 " + integerList);
// 查找元素是否存在该集合
integerList.contains(99);
System.out.println("集合中是否存在元素99 = " + integerList.contains(99));
// 判断一个集合是否在另一个集合中全部存在(是不是包含关系)
integerList.containsAll(integerList2);
System.out.println("integerList = " + integerList);
System.out.println("integerList2 = " + integerList2);
System.out.println("integerList集合中是否包含integerList2集合 " + integerList.containsAll(integerList2));
// 查找index索引位的元素的值并返回
integerList.get(4);
System.out.println("integerList = " + integerList);
System.out.println("第四位的元素的值 " + integerList.get(4));
// 判断集合是否为空
integerList.isEmpty();
System.out.println("integerList集合是否为空 " + integerList.isEmpty());
// 修改某个位置的元素的值
integerList.set(5,123);
System.out.println("integerList = " + integerList);
System.out.println("将第五位元素修改为123 返回 " + integerList.set(5, 123));
// 将一个集合转换为数组
Integer[] integers = integerList.toArray(new Integer[0]);
System.out.println("***************************************");
System.out.println(Arrays.toString(integers));
integers[0]=999;
System.out.println(Arrays.toString(integers));
System.out.println("***************************************");
// 注意,此时的Arrays.asList()这个方法是返回的是Arrays里的内部类ArrayList<>(a)
List<Integer> integers1 = Arrays.asList(integers);
System.out.println(integers1);
// 将一个数组转化成List之后,可以更改List中的值。
// 但是不能向List中添加,删除数据,因为现在的操作是对原来的数组的操作
// integers1.add(96325);
// integers1.remove(8);
integers1.set(2,45698);
System.out.println(integers1);
System.out.println("***************************************");
// 截取集合中的一段
integerList.subList(4,9);
System.out.println("integerList.subList(4,9) = " + integerList.subList(4, 9));
// 获取迭代器对象,遍历集合
Iterator<Integer> iterator = integerList.iterator();
System.out.println("遍历集合如下: ");
while (iterator.hasNext())
System.out.print(iterator.next()+"\t");
// 获取集合的长度,即元素的个数(null也算一个元素)
integerList2.size();
integerList2.add(null);
integerList2.add(null);
integerList2.add(958);
integerList2.add(6523);
System.out.println("integerList2 = " + integerList2);
System.out.println("integerList2中的元素个数 " + integerList2.size());
// 最小化该集合的储存空间,只是这个方法是在List的实现类中定义的,我用了多态来实例化对象,而List中没有定义这个方法,所以需要向下转型一下来调用
((ArrayList<Integer>) integerList).trimToSize();
// 求两个集合的交集
System.out.println("integerList = " + integerList);
System.out.println("integerList2 = " + integerList2);
System.out.println("integerList集合和integerList2集合的交集为 = " + integerList.retainAll(integerList2));
System.out.println("integerList = " + integerList);
System.out.println("integerList2 = " + integerList2);
// 清除集合的所有元素
integerList.clear();
integerList2.clear();
System.out.println("integerList = " + integerList);
System.out.println("integerList2 = " + integerList2);
}
/**
* LinkedList集合常用方法,写LinkedList自己定义的方法
*/
@Test
public void Test4(){
// 底层使用的是双向链表
List<Integer> integerList2 = new LinkedList<>();
integerList2.add(99);
integerList2.add(99);
integerList2.add(99);
integerList2.add(99);
List<Integer> integerList = new LinkedList<>();
integerList.add(45);
integerList.add(75);
integerList.add(99);
integerList.add(99);
integerList.add(99);
integerList.add(65);
integerList.add(84);
integerList.add(98);
// 因为add()的是一个对象,所以可以添加null,也会算在size()里
integerList.add(null);
integerList.add(null);
integerList.add(84);
integerList.add(65);
System.out.println("integerList = " + integerList);
// 返回集合的元素个数
integerList.size();
System.out.println("integerList.size() = " + integerList.size());
// 对这个集合排序并输出 排序后是生成了个新数组,不会改变原数组,类比String
System.out.println("integerList = " + integerList);
integerList.sort((o1, o2) -> {
if (o1==null&&o2==null) return 0;
if (o1==null) return -1;
if (o2==null) return -1;
if (o1>o2) return 1;
if (o1==o2) return 0;
if (o1<o2) return -1;
throw new RuntimeException("程序异常");
});
Iterator<Integer> iterator = integerList.iterator();
System.out.println("排序后");
while (iterator.hasNext())
System.out.print(iterator.next()+"\t");
// 在集合首位插入数据
integerList.add(0,987);
integerList.indexOf(45);
// 判断集合integerList是否包含integerList2
System.out.println("integerList = " + integerList);
System.out.println("integerList2 = " + integerList2);
System.out.println("integerList.containsAll(integerList2) = " + integerList.containsAll(integerList2));
}
最后需要注意的一点是用Arrays.asList(T... a)将一个数组转换成一个集合后,不能对其进行增加,删除,改变的操作,不然会报错。
因为Arrays.asList(T... a)这个方法返回的List<T>是Arrays里的内部类ArrayList<>,不是java.util下的List 。
Arrays里的ArrayList<>这个内部类里没有提供add(),remove()方法,所以通过多态来调用add(),remove()的时候,会抛异常,方法没有定义 。
但是,Arrays里的ArrayList<>这个内部类里定义了get(),set(),contains(),toArray(),indexOf(),replaceAll(),sort()这些方法 。