Java集合框架(二)-----List接口

一、 Collection接口之一(List接口):

单列数据,定义了存取一组对象的方法的集合
List:存储有序,可重复的数据 --“动态数组”,替换原有的数组

1、List接口的实现类:

ArrayList:作为List接口的主要实现类,线程不安全,效率高,底层使用Object[] elementDate存储
LinkedList:对于频繁插入和删除操作,使用此类效率比ArrayList的效率高,底层使用的是双向链表存储
Vector:在jdk1.0版本就存在,开发中基本不用,线程安全,效率低,底层使用Object[] elementDate存储

2、 ArrayList的源码分析:底层在你造对象的时候就实例化了(单例模式饿汉式)

2.1.jdk7: ArrayList list = new ArrayList();//底层创建了长度为10的Object的数组elementData
list.add(123);//elementData[0] = new Integer(123);

list.add(11)//当新添加的元素的个数超过10个(容量不够),则扩容,默认情况下,扩容为原来的1.5倍
同时需要将原有数组中的数据复制到新的数组中

结论:建议开发中使用带参的构造器:ArrayList list = new ArrayList(int capacity)

2.2、jdk8中ArrayList的变化:造对象时对象未创建为:{},在第一次调用add时才实例化(单例模式懒汉式)
ArrayList list = new ArrayList();//底层的Object[]的数组elementData初始化为{}, 并没有创建长度为10的数组

list.add(123);//第一次调用add()时,底层创建了长度为10的数组,并将数据添加到elementData[0]中

list.add(11)//当新添加的元素的个数超过10个(容量不够),则扩容,默认情况下,扩容为原来的1.5倍
同时需要将原有数组中的数据复制到新的数组中

结论:延迟了数组的创建,节省内存

3、LinkedList的源码分析

LinkedList list = new LinkedList();//内部创建了Node类型的first和last属性,默认值为null
list.add(123);//将123封装到Node中,创建了Node的对象
该代码体现了LinkedList的双向链表
private static class Node {
E item;
Node next;
Node prev;

Node(Node prev, E element, Node next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}

4.Vector的源码分析:

jdk7和8中通过Vector()构造器创建对象时,底层都创建了长度为10的数组在扩容时,默认扩容为原来数组长度的2倍

5.list接口中的常用方法

1、将指定的元素,添加到该集合中的指定位置上。
public void add(int index, E element)

2、boolean addAll(int index, Collection<? extends E> c)
在指定的位置中插入c集合全部的元素,如果集合发生改变,则返回true,否则返回false。

3、返回集合中指定位置的元素。
public E get(int index)

4、移除列表中指定位置的元素,返回的是被移除的元素。
public E remove(int index)

5、用指定元素替换集合中指定位置的元素,返回值的更新前的元素。
public E set(int index, E element)

6、int indexOf(Object o)
返回list集合中第一次出现o对象的索引位置,如果list集合中没有o对象,那么就返回-1

7.int lastIndexOf(Object o)
返回list集合中末次出现o对象的索引位置

8、List subList(int fromIndex, int toIndex)
返回从索引fromIndex到toIndex的元素集合,包左不包右

总结:常用方法
增:add(Object o):
删:remove(int index)/remove(Object o)
改:set(int index,Object o)
查: get(int index)
插:add(int index, E element)
长度:size()
遍历:①Iterator迭代器 ② forEach ③ for

面试题:区分list中的remove中的两种方法

 @Test
    public void test2(){
        List list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        updateList(list);
        System.out.println(list);//[1, 2]
    }
    private static void updateList(List list){
//        list.remove(2);
        list.remove(new Integer(2));
    }
    @Test
    public void test(){
        ArrayList list = new ArrayList();

        list.add(123);
        list.add(456);
        list.add(new String("Tom"));
        list.add(false);
        //详细可见Java集合框架(一)-----Collection接口中的Person类
        list.add(new Person("Tom", 20));
        list.add(456);
        //默认调用toString方法
        System.out.println(list);//[123, 456, Tom, false, Person{name='Tom', age=20}]

        //1.public void add(int index, E element)
        list.add(1,"BB");
        System.out.println(list);

        //2、boolean addAll(int index, Collection<? extends E> c)
        List list1 = Arrays.asList(1,2,3);
        list.addAll(list1);
        System.out.println(list.size());//9

        //3.public E get(int index)
        System.out.println(list.get(0));//123

        //4.int indexOf(Object o)
        int i = list.indexOf(456);
        System.out.println(i);//2(前面添加了一个BB),不存在-1

        //5.int lastIndexOf(Object o)
        System.out.println(list.lastIndexOf(456));

        //6.public E remove(int index):可以按照索引和对象两种方法来进行删除
        Object remove = list.remove(0);
        System.out.println(remove);//返回被删除的元素
        System.out.println(list);//[BB, 456, Tom, false, Person{name='Tom', age=20}]

        //7.public E set(int index, E element)
        list.set(1,"C");
        System.out.println(list);

        //8、List<E> subList(int fromIndex, int toIndex)
        List list2 = list.subList(2, 4);//返回被指定的元素,原来的没有变化
        System.out.println(list2);//[Tom, false]
    }
六、 面试题: ArrayList LinkedList Vector 三者的异同

相同点:三个类都实现了List接口,存储数据的特点相同:存储有序的,可重复的数据
不同点:见上1,2,3,4点

发布了19 篇原创文章 · 获赞 0 · 访问量 482

猜你喜欢

转载自blog.csdn.net/weixin_43244120/article/details/105496895