List的实现类ArrayList,LinkedList,Vector对比及其常用方法的运用

|----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()这些方法 。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

soutv

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值