zoukankan      html  css  js  c++  java
  • Java 之 List 接口

    一、List 接口介绍

      java.util.List 接口继承自 Collection 接口,是单列集合的一个重要分支,习惯性地会将实现了 List 接口的对象称为 List 集合

      在 List 集合中允许出现重复的元素,所有的元素以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素。

      List 集合的另一个特点就是元素有序,即元素的存入顺序和取出顺序一致。

      小结:List 接口的特点

        1、它是一个元素存取有序的集合。例如:存入元素顺序为1,2,3,那么集合中,元素的存储就是安装1,2,3,的顺序完成的。

        2、它是一个带有索引的集合。通过索引就可以精确的操作集合中的元素(与数组索引同理)

        3、集合中可以有重复的元素通过元素的 equals 方法,来比较是否为重复的元素。

      扩展

        在操作索引的时候,一定要放置索引越界异常。

    IndexOutOfBoundsException:索引越界异常,集合会报
    ArrayIndexOutOfBoundsException:数组索引越界异常
    StringIndexOutOfBoundsException:字符串索引越界异常

    二、List 接口中常用方法

      List 作为 Collection 集合的子接口,不但继承了 Collection 接口中的全部方法,而且还增加了一些根据元素索引来操作集合的特有方法。

      1、添加元素

     void add(int index, E element) :在列表的指定位置插入指定元素
     boolean addAll(int index, Collection<? extends E> c) : 将指定 collection 中的所有元素都插入到列表中的指定位置 

      2、删除元素

     E remove(int index) :移除列表中指定位置的元素 
     boolean removeAll(Collection<?> c) :从列表中移除指定 collection 中包含的其所有元素 

      3、获取元素

     E get(int index): 返回列表中指定位置的元素。 
     List<E> subList(int fromIndex, int toIndex):返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图 

      4、获取元素索引

    int indexOf(Object o) :返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1 
    int lastIndexOf(Object o):返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。 

      5、替换元素

     E set(int index, E element):用指定元素替换列表中指定位置的元素 

      6、获取迭代器

    Iterator<E> iterator() :返回按适当顺序在列表的元素上进行迭代的迭代器 
    ListIterator<E> listIterator() :返回此列表元素的列表迭代器(按适当顺序)
    ListIterator<E> listIterator(int index) :返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始  
    

          ListIterator 是 Iterator 的子接口,它比 Iterator增加了:从后往前遍历的方法,增加了遍历的同时添加和修改。

         Iterator 的常用方法:

    boolean hasNext() :如果仍有元素可以迭代,则返回 true。 
    E next():返回迭代的下一个元素。 
    void remove() :从迭代器指向的 collection 中移除迭代器返回的最后一个元素 

         ListIterator 的常用方法:

    boolean hasPrevious():如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。
    E previous():返回列表中的前一个元素  
    void add(E e):遍历的同时,将指定的元素插入列表 
    void set(E e):遍历的同时,用指定元素替换 next 或 previous 返回的最后一个元素 
    int nextIndex():返回对 next 的后续调用所返回元素的索引 
    int previousIndex():返回对 previous 的后续调用所返回元素的索引 
    

            Demo:

     1 @Test
     2 public void test6(){
     3     List list = new ArrayList();  //使用多态,更多的关注 List 接口方法
     4         
     5     list.add(1);
     6     list.add(2);
     7     list.add(3);
     8     list.add(4);
     9     list.add(5);    
    10     
    11     ListIterator listIterator = list.listIterator();
    12     while(listIterator.hasNext()){
    13         Object obj = listIterator.next();
    14         System.out.println(obj);   //遍历结果:1,2,3,4,5
    15     }
    16     System.out.println("-------------------------");
    17     while(listIterator.hasPrevious()){
    18         Object obj = listIterator.previous();
    19         System.out.println(obj);  //遍历结果:5,4,3,2,1
    20     }
    21     System.out.println("-------------------------");
    22     //ListIterator listIterator = list.listIterator();//默认游标在开头
    23     ListIterator listIterator2 = list.listIterator(list.size());//把游标指定到后面去
    24     while(listIterator2.hasPrevious()){
    25         Object obj = listIterator2.previous();
    26         System.out.println(obj); //遍历结果:5,4,3,2,1
    27     }
    28     System.out.println("-------------------------");
    29     ListIterator listIterator3 = list.listIterator(3);//把游标指定到任意位置
    30     while(listIterator3.hasPrevious()){
    31         Object obj = listIterator3.previous();
    32         System.out.println(obj); //遍历结果:3,2,1
    33     }
    34 }

      注意虽然List系列的集合都是可以通过索引/下标进行操作的,但是像LinkedList这类的集合,其实不建议使用和索引相关的方法进行操作。因为它们的底层的物理结构不是数组,如果通过索引操作呢,会需要从头或尾遍历找到对应的索引,效率不高。

    三、List接口的实现类

      Vector 类:动态数组

      ArrayList 类:动态数组

      Stack 类:栈(Vector的子类)

      LinkedList 类:双向链表(从 JDK1.6之后又实现了双端队列)

      1、ArrayList 与 Vector 的区别?

        它们的底层物理结构都是数组,我们称为动态数组

        ① ArrayList是新版的动态数组,线程不安全,效率高;Vector是旧版的动态数组,线程安全,效率低。

        ② 动态数组的扩容机制不同,ArrayList扩容为原来的1.5倍,Vector扩容增加为原来的2倍。所以会造成下面问题:a、2倍情况下,造成空间浪费的可能性比较大;b、1.5倍情况下,造成扩容的次数增大

        ③ 数组的初始化容量,如果在构建ArrayList与Vector的集合对象时,没有显式指定初始化容量,那么Vector的内部数组的初始容量默认为10,而ArrayList在JDK1.6及之前的版本也是10,而JDK1.7之后的版本ArrayList初始化为长度为0的空数组,之后在添加第一个元素时,再创建长度为10的数组。

        Vector和ArrayList的使用时,为了比较空间浪费,和扩容次数太多,如果能够预估大概的元素个数,那么可以用 ArrayList(int initialCapacity)和Vector(int initialCapacity)直接初始化为一定容量的数组。

        ④ Vector因为版本古老,支持Enumeration 迭代器。但是该迭代器不支持快速失败。而Iterator和ListIterator迭代器支持快速失败。如果在迭代器创建后的任意时间从结构上修改了向量(通过迭代器自身的 remove 或 add 方法之外的任何其他方式),则迭代器将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就完全失败,而不是冒着在将来不确定的时间任意发生不确定行为的风险。

        提示:在List列表集合实现中都有一个变量modCount,每次添加、删除都会使得modCount变量增加,因此用foreach和Iterator迭代时,如果再通过集合的add和remove等方法修改集合,会抛出 ConcurrentModificationException。

      2、Vector 与 Stack 的区别与联系?

        Stack类是Vector的子类。

        Stack类表示后进先出(LIFO)的对象堆栈。它通过五个操作对类 Vector 进行了扩展 ,允许将向量视为堆栈。它提供了通常的 push 和 pop 操作,以及取堆栈顶点的 peek 方法、测试堆栈是否为空的 empty 方法、在堆栈中查找项并确定到堆栈顶距离的 search 方法。

    四、List 集合的遍历

      1、普通 for 循环遍历

        对于 ArrayList 和 Vector 这样的动态数组,可以使用普通的 for 循环进行遍历。

      2、迭代器遍历

        可以通过 list 集合获取 Iterator 或 ListIterator 对象,来实现对集合的遍历

      3、增强 for 循环

     

  • 相关阅读:
    精细化python 类的内置属性
    python操作excel
    ghost linux
    Linux dd 命令
    Ubantu 使用root登陆的方法
    NSIS Error: "Error writing temporary file. Make sure your temp folder is valid
    error writing temporary file。make sure your temp folder is valid 问题已解决
    安卓电池状态监听
    Android源码下载
    vim插件详细安装过程
  • 原文地址:https://www.cnblogs.com/niujifei/p/11438962.html
Copyright © 2011-2022 走看看