集合(Collection子接口——List接口)
List接口
鉴于Java中数组用来存储数据的局限性,我们通常使用List(动态数组)替代数组
List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。 List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。 JDK API中List接口的实现类常用的有:ArrayList、LinkedList和Vector(现在基本没有人使用了)。
List除了从Collection集合继承的方法外,List 集合里添加了一些根据索引(区别于set)来操作集合元素的方法。 void add(int index, Object ele):在index位置插入ele元素 boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来 Object get(int index):获取指定index位置的元素 int indexOf(Object obj):返回obj在集合中首次出现的位置,如果不存在返回 -1 int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置 Object remove(int index):移除指定index位置的元素,并返回此元素(重载了Ccllection的remove方法) Object set(int index, Object ele):设置指定index位置的元素为ele List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置(左闭右开)的子集合,原来的list并没有变化。
ArrayList
ArrayList 源码分析
jdk7 : ArrayList list = new ArrayList(); // 底层会直接创建了长度为10的 Object[] 数组 elementData list.add(123); ··· ··· list(11);// 当添加的元素个数超过了10,之后数组的容量就不够了,就会发生扩容,但这些不需要我们自己去动手,在底层直接会自动扩容,一般情况下是扩容1.5倍,同时将原数组的元素复制到新数组上。 结论:建议使用代参的构造器,ArrayList list = new ArrayList(int capacity); capacity在这里指的是数组的长度。
jdk8: ArrayList list = new ArrayList(); // 底层是 Object[] 数组 elementData{},说明在我们创建对象的时候没有直接给定长度。 list.add(123); //但是当第一次执行add方法时,才会创建长度为10 的数组。 其余的扩容方法都与jdk7中一样。
小结:jdk7中的ArrayList 对象的创建模式相当于单例模式中的饿汉式,jdk8中的ArrayList 对象的创建模式相当于单例模式中的懒汉式,延迟了数组的创建,节省了内存。
LinkedList
新增方法: void addFirst(Object obj) void addLast(Object obj) Object getFirst() Object getLast() Object removeFirst() Object removeLast()
LinkedList:双向链表,内部没有声明数组,而是定义了Node类型的first和last,用于记录首末元素。同时,定义内部类Node,作为LinkedList中保存数据的基本结构。Node除了保存数据,还定义了两个变量: prev变量记录前一个元素的位置 next变量记录下一个元素的位置
LinkedList源码分析
其实跟我前几天写的单链表差不过,只不过在节点类中多加了一个指针,能指向上一个节点,这样就能在底层构成双向链表。其实看图就很容易懂了,不懂可以翻翻我之前写的单链表的api。
面试题
面试题:ArrayList、LinkedList和Vector的异同 相同:三个类都是实现了List接口,存储数据都是有序的,可重复的。 不同: ArrayList:作为List接口的主要实现类,线程不安全,效率高。而在调用get和set方法时,使用ArrayList会比LinkedList更快捷。底层使用Object[] 存储。 LinkedList:线程不安全。对于频繁的插入和删除操作时,使用此类比ArrayList效率高。底层使用的是双向链表存储。 Vector:作为List接口的古老实现类,线程安全的,效率低。底层使用Object[] 存储。Vector每次扩容请求其大小的2倍空间,而ArrayList是1.5倍。
面试题:
public void testListRemove() {
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
updateList(list);
System.out.println(list);
}
private static void updateList(List list) {
list.remove(2);
}
输出的结果为:
1
2
因为我这个remove方法是根据索引删除的,所以删除的是 3 这个元素。如果想要删除2这个元素应该这么写
list.remove(new Integer(2));//这样才表示删除的是2 这个元素 ,而不是索引。
|