一、List 接口介绍

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

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

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

  小结:List 接口的特点

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

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

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

  扩展

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

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

二、List 接口中常用方法

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

  1、添加元素

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

  2、删除元素

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

  3、获取元素

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

  4、获取元素索引

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

  5、替换元素

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

  6、获取迭代器

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

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

     Iterator 的常用方法:

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

     ListIterator 的常用方法:

  1. boolean hasPrevious():如果以逆向遍历列表,列表迭代器有多个元素,则返回 true
  2. E previous():返回列表中的前一个元素
  3. void add(E e):遍历的同时,将指定的元素插入列表
  4. void set(E e):遍历的同时,用指定元素替换 next previous 返回的最后一个元素
  5. int nextIndex():返回对 next 的后续调用所返回元素的索引
  6. 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 循环

Java 之 List 接口的更多相关文章

  1. 【转】java通用URL接口地址调用方式GET和POST方式

    java通用URL接口地址调用方式GET和POST方式,包括建立请求和设置请求头部信息等等......... import java.io.ByteArrayOutputStream; import ...

  2. Java继承和接口

    接口最关键的作用,也是使用接口最重要的一个原因:能上溯造型至多个基础类.使用接口的第二个原因与使用抽象基础类的原因是一样的:防止客户程序员制作这个类的一个对象,以及规定它仅仅是一个接口.这样便带来了一 ...

  3. java中set接口的用法

    java中的set接口有如下的特点: 不允许出现重复元素: 集合中的元素位置无顺序: 有且只有一个值为null的元素. 因为java中的set接口模仿了数学上的set抽象,所以,对应的数学上set的特 ...

  4. Java调用webservice接口方法

                             java调用webservice接口   webservice的 发布一般都是使用WSDL(web service descriptive langu ...

  5. Java面向对象:接口

    Java面向对象之接口 什么是接口:接口是一种规范和标准,他们可以约束类的行为,是一些方法特征的集合 语法: [修饰符] interface 接口名 extends 父接口1,夫接口2....... ...

  6. JAVA ,Map接口 ,迭代器Iterator

    1.    Map 接口概述 java.util.Map 接口描述了映射结构, Map 接口允许以键集.值集合或键 - 值映射关系集的形式查看某个映射的内容. Java 自带了各种 Map 类. 这些 ...

  7. java抽象类和接口区别

    深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...

  8. java抽象类与接口的区别及用法

    java抽象类与接口的区别及用法 一.抽象类里面的方法可以有实现,但是接口里面的方法确是只能声明. 二.接口是设计的结果 :抽象类是重构的结果 . 三.java不支持多重继承,所以继承抽象类只能继承一 ...

  9. 如何让Java和C++接口互相调用:JNI使用指南

    如何让Java和C++接口互相调用:JNI使用指南 转自:http://cn.cocos2d-x.org/article/index?type=cocos2d-x&url=/doc/cocos ...

  10. Java中的队列:java.util.Queue接口

    队列是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作. Queue接口与List.Set同一级别,都是继承了Collection接口.Linked ...

随机推荐

  1. el获取对象属性大小写问题

    当el表达式首字母大写,会判断第二个字母大小写,小写,抛异常:大写,则直接拼接get,形成getter方法 当el表达式首字母小写,会判断第二个字母大小写,大写,必须第一个字母大写:否则无法获取值 e ...

  2. Python进阶-III 函数装饰器(Wrapper)

    1.引入场景: 检查代码的运行时间 import time def func(): start = time.time() time.sleep(0.12) print('看看我运行了多长时间!') ...

  3. 【pytorch】torch.utils.data.DataLoader

    简介 DataLoader是PyTorch中的一种数据类型.用于训练/验证/测试时的数据按批读取. torch.utils.data.DataLoader(dataset, batch_size=1, ...

  4. 原题链接在这里:980. Unique Paths III

    原题链接在这里:https://leetcode.com/problems/unique-paths-iii/ 题目: On a 2-dimensional grid, there are 4 typ ...

  5. MongoDB executionStats 详细分步查询计划与分步时间(转载)

    mongodb性能分析方法:explain() 为了演示的效果,我们先来创建一个有200万个文档的记录.(我自己的电脑耗了15分钟左右插入完成.如果你想插更多的文档也没问题,只要有耐心等就可以了.) ...

  6. 深入js系列-类型(null)

    首先null是表示什么状态呢 这个是需要和上篇的undefined做一个区分 undefined 从未赋值 非关键词(也就是可以定义为变量名或者赋值给它) null 曾经赋值.目前没值 关键词 typ ...

  7. matplotlib折线图

    绘制折线图:参考https://baijiahao.baidu.com/s?id=1608586625622704613           (3)近10年GDP变化的曲线图,及三次产业GDP变化的曲 ...

  8. vue添加背景音乐

    vue添加背景音乐需要用到HTML中的标签 参考手册:http://www.w3school.com.cn/tags/html_ref_audio_video_dom.asp *在iOS端autopl ...

  9. Log4j之HelloWorld

    在编写项目的时候,我们一般都会用到日志记录,方便出错查找原因.首先我们需要了解什么是Log4j 1.使用maven建立工程,在pom.xml中加入如下: <dependency> < ...

  10. Python3.7 - Argparse模块的用法

    argparse 是一个命令行参数解析模块. argparse 是python自带的命令行参数解析包,可以用来方便地读取命令行参数,当你的代码需要频繁地修改参数的时候,使用这个工具可以将参数和代码分离 ...