/
*
- /* 1.List接口框架
-
-
|----Collection接口:单列集合,用来存储一个一个的对象
-
-
-
|----List接口:存储有序的、可重复的数据。 -->“动态”数组
-
-
-
不同:
-
-
* ArrayList、: List接口的主要实现类 线程不安全的 效率高,底层使用Object[] 存储
-
-
LinkedList、:底层使用双向链表 存储,对于频繁的插入、删除操作,使用此类效率比ArrayList高
-
-
-
Vector: List接口的古老实现类 线程 安全的
-
-
-
- 2.ArrayList源码分析:
-
-
2.1 JDK7: ArrayList list = new ArrayList();//底层创建了长度是10的Object[]数组elementData
-
-
list.add(123);//数组elementData[0] = new Integer(123)
-
...
-
list.add(11);//如果此次添加的导致底层elementData数组容量不够,则扩容,默认情况下扩容为原来的1.5倍,
-
同时需要将原有数组中的数据复制到新的数组中。
-
结论: 建议开发中使用带参的构造器 ArrayList list = new ArrayList(int capacity)
-
2.2 JDK8中变化:
-
ArrayList list = new ArrayList();//底层Object[] elementData初始化为{}.
-
并没有创建了长度是10的Object[]数组。
-
第一次调用list.add(123)的时候才底层长度是10的Object[]数组,并将123添加到elementData[0]
-
后续添加和扩容操作和JDK7无异。
-
2.3 小结:JDK7的ArrayList创建类似于单例模式中的饿汉式,JDK8的ArrayList对象创建类似于单例模式中的懒汉式,
-
延迟了数组创建,节省了内存
-
- 3.LinkedList源码分析:
-
LinkedList list = new LinkedList(); 内部声明了Node类型的first和last属性,默认值为null
-
调用list.add(123);的时候//将123封装到Node里,创建了Node对象
-
其中Node定义为:(双向链表)
-
private static class Node<E> {
-
E item;
-
Node<E> next;
-
Node<E> prev;
-
Node(Node<E> prev,E element, Node<E> next){
-
this.item = element;
-
this.next = next;
-
this.prev = prev;
-
}
-
}
-
4.Vector源码分析:jdk 7 8 通过构造器创建对象时,创建长度为十的数组,扩容时扩容为原数组长度的2倍。线程安全,扩容方式不一样
- *面试题:
-
- ArrayList,LinkedList,Vector三者的异同?
-
- 相同点:三个类都实现了List接口,存储数据的特点相同,:存储有序的可重复的数据。
-
- 不同:
- /*
方法测试
public class ListTest {
@Test
public void test1() {
List list = new ArrayList();
list.add(123);
list.add(456);
list.add("AA");
list.add(new Person("Tom", 12));
list.add(456);
System.out.println(list);
//1.插入1的位置
list.add(1, "BB");
System.out.println(list);
//2.把list中元素插入到后面
List list1 = Arrays.asList(1, 2, 3);
list.addAll(list1);
System.out.println(list.size()); // 9
//3.Object get(int index):获取指定index位置的元素
System.out.println(list.get(0)); // 123
}
@Test
public void test2() {
ArrayList list = new ArrayList();
list.add(123);
list.add(456);
list.add("AA");
list.add(new Person("Tom", 12));
list.add(456);
//4.int indexOf(Object obj):返回obj在集合中首次出现的位置。如果不存在,返回-1.
int index = list.indexOf(4567);
System.out.println(index); // -1
//5.int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置。如果不存在,返回-1.
System.out.println(list.lastIndexOf(456)); // 4
//Object remove(int index):移除指定index位置的元素,并返回此元素
Object obj = list.remove(0);
System.out.println(obj); // 123
System.out.println(list); // [456, AA, Person{name='Tom', age=12}, 456]
//Object set(int index, Object ele):设置指定index位置的元素为ele
list.set(1, "CC");
System.out.println(list); // [456, CC, Person{name='Tom', age=12}, 456]
//List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的左闭右开区间的子集合
List subList = list.subList(2, 4);
System.out.println(subList); // [Person{name='Tom', age=12}, 456]
System.out.println(list); // [456, CC, Person{name='Tom', age=12}, 456],本身没有变化
}
- 总结常用方法:
-
增 add(Object obj)
-
删 remove(int index) / remove(Object obj)
-
改 set(int index, Object ele)
-
查 get(int index)
-
插入 add(int index , Object obj)
-
长度 size()
-
遍历 1.Iterator迭代器 2.增强for循环 3.普通循环
@Test
public void test3() {
ArrayList list = new ArrayList();
list.add(123);
list.add(456);
list.add("AA");
// 方式一:Iterator迭代器方式
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
System.out.println("***********************");
// 方式二: 增强for循环
for (Object obj : list) {
System.out.println(obj);
}
//方式三:普通for循环
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
面试小题
面试题1:
-
- ArrayList,LinkedList,Vector三者的异同?
-
- 相同点:三个类都实现了List接口,存储数据的特点相同,:存储有序的可重复的数据。
-
- 不同:ArrayList、: List接口的主要实现类 线程不安全的 效率高,底层使用Object[] 存储
-
-
LinkedList、:底层使用双向链表 存储,对于频繁的插入、删除操作,使用此类效率比ArrayList高
-
-
-
Vector: List接口的古老实现类 线程 安全的
-
面试题2:区分List中remove(int index)和remove(Object obj)
public class ListExer {
// 区分List中remove(int index)和remove(Object obj)
@Test
public void test(){
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
updateList(list);
System.out.println(list);
}
// public void updateList(List list){
// list.remove(new Integer(2)); // 1 3
// }
public void updateList(List list){
list.remove(2); // 1 2
}
}