一:先看看集合框架接口图

(图片来源于网络)

从图中可以看到List实现了Collection接口。

二:Collection接口是什么?

在java类库中,Collection接口是集合类的基本接口,这个接口有两个基本的方法:

public interface Collection<E> extends Iterable<E>
{boolean add(E element);Iterator<E> iterator();...
}

add方法用于向集合中添加元素。如果添加元素确实改变了集合就返回true,如果集合没有发生改变就返回false。列如,向一个   集合中添加一个已经存在的对象,这个添加请求就没有效果会返回false,因为Set集合不允许重复对象。从代码中可以看到,       Collection接口还包括了一个iterator()方法,返回类型为Iterator接口对象,那么什么Iterator接口?

Collection接口中的其它方法:

//添加方法:
add(Object o) //添加指定元素
addAll(Collection c) //添加指定集合
//删除方法:
remove(Object o) //删除指定元素
removeAll(Collection c) //输出两个集合的交集
retainAll(Collection c) //保留两个集合的交集
clear() //清空集合
//查询方法:
size() //集合中的有效元素个数
toArray() //将集合中的元素转换成Object类型数组
//判断方法:
isEmpty() //判断是否为空
equals(Object o) //判断是否与指定元素相同
contains(Object o) //判断是否包含指定元素
containsAll(Collection c) //判断是否包含指定集合

List接口中的方法

//添加方法:
add(int index, Object o) //向指定位置添加元素
addAll(int index, Collection c) //向指定位置添加集合
//删除方法
remove(int index) //删除指定元素
//查询方法:
get(int index) //获取指定位置的元素
indexOf(Object o) //获取指定元素的位置
lastIndexOf(Object o) //获取指定元素最后一次出现的位置
//修改方法:
subList(int fromIndex, int toIndex) //截取子集合从fromIndex到toIndex,要头不要尾
set(int index, Object o) //修改指定位置的元素

三:迭代器

翻看Iterator接口源码

public interface Iterator<E> {boolean hasNext();E next();default void remove() {throw new UnsupportedOperationException("remove");}default void forEachRemaining(Consumer<? super E> action) {Objects.requireNonNull(action);while (hasNext())action.accept(next());}
}

很明显的可以看到,这个Iterator接口就像当于链表中的结点,只不过在C语言里结点里的指针在java中变成了对象的引用。那么 我们就应该知道,通过反复的调用nest()就可以逐个的访问集合中的每个元素,但是当到达了集合的末尾,nest方法将抛出一个NoSuchElementException。因此,每次都用next方法前都应该调用hasNext方法进行判断。hasNext方法的作用是判断对象是否还有下一个元素,有就返回true,否则返回false。remove方法会删除上次调用next方法时返回的元素。就像是删除一个元素之前先看下它是很有必要的,remove方法就是按照这个理念设计的。举一个访问集合中所有元素的案例:

 Collection<String> s = new ArrayList<String>();s.add("xiaohong");s.add("xionming");s.add("wanger");Iterator<String> iterator = s.iterator();while(iterator.hasNext()) {String element = iterator.next();System.out.println(element);}

在Java SE8版本中,新加入了for each循环遍历,编译器简单地将“for each”循环翻译为带有迭代器的循环。

for (String string : s){System.out.println(string);}

显然,通过"for each"遍历使得代码更加简洁,所有实现了Iterable接口的对象都可以使用"for each"循环。Collection接口扩展了Iterable接口。

四:具体的实现类

1.AbstractList

如果实现了Collection接口的每一个类都要实现它的所有方法,那么将是一件很烦的事情。此时,AbstractList应运而生。

它将基础的iterator抽象化,其它的方法给实现了,此时一个具体的集合类就可以扩展AbstractList类,并且只需提供Iterator方法,当然如果不满意AbstractList类实现的方法也可以在子类重写它的方法。

2.ArrayList

ArrayList 的底层是数组队列,相当于动态数组。与 Java 中的数组相比,它的容量能动态增长。在添加大量元素前,应用程序可以使用ensureCapacity操作来增加 ArrayList 实例的容量。这可以减少递增式再分配的数量。

它继承于 AbstractList,实现了 List, RandomAccess, Cloneable, java.io.Serializable 这些接口。

在我们学数据结构的时候就知道了线性表的顺序存储,插入删除元素的时间复杂度为O(n),求表长以及增加元素,取第 i 元素的时间复杂度为O(1)

  • ArrayList 继承了AbstractList,实现了List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。
  • ArrayList 实现了RandomAccess 接口, RandomAccess 是一个标志接口,表明实现这个这个接口的 List 集合是支持快速随机访问的。在 ArrayList 中,我们即可以通过元素的序号快速获取元素对象,这就是快速随机访问。
  • ArrayList 实现了Cloneable 接口,即覆盖了函数 clone(),能被克隆。
  • ArrayList 实现java.io.Serializable 接口,这意味着ArrayList支持序列化,能通过序列化去传输。

  和 Vector 不同,ArrayList 中的操作不是线程安全的!所以,建议在单线程中才使用 ArrayList,而在多线程中可以选择 Vector 或者 CopyOnWriteArrayList。

ArrayList中特有的方法

ensureCapacity(int minCapactiy) //判断当前数组中的元素个数是否大于指定的minCapacity
trimToSize() //修改数组容量为当前数组有效元素个数

3.LinkedList

LinkedList是一个实现了List接口和Deque接口的双端链表。 LinkedList底层的链表结构使它支持高效的插入和删除操作,另外它实现了Deque接口,使得LinkedList类也具有队列的特性; LinkedList不是线程安全的,如果想使LinkedList变成线程安全的,可以调用静态类Collections类中的synchronizedList方法.。

需要提一下的是,LinkedList类中有一个ListIterator<E> listIterator方法,listIterator接口中包含一个add方法:

public interface ListIterator<E> extends Iterator<E> {boolean hasNext();E next();boolean hasPrevious();void set(E e);void add(E e);
}

因为链表是一个有序的集合,每个对象的位置就显得十分重要。LinkedList中的add方法只能将对象添加到链表尾部,而经常却要将对象添加到链表的中间,迭代器就是用于描述集合中的位置的,所以这种依赖位置的方法就交由迭代器来完成。因为Set集合是无序的,所以在Iterator接口中就没有add方法,而是扩展了一个LinkIterator接口来实现。

值得一提的是:大家都知道,链表是不支持快速随机访问的。如果要查看链表中的第n个元素,就必须从头开始,越过n-1个元素,没有捷径可走,但尽管如此,LinkedList还是提供了一个用来访问某个特定元素的get方法,当然这个方法的效率并不高,如果在使用这个方法,那么可能对于所要解决的问题使用了错误的数据结构。LinkedList类中get方法所谓的随机访问都是需要从列表的头部开始搜索,效率极低。使用链表的唯一理由是尽可能的减少在链表中间插入或删除元素所付出的代价。

LinkedList中特有的方法

//查询方法:
getFirst() //获取集合中的第一个元素
getLast() //获取集合中的最后一个元素
//添加方法:
addFirst(Object o) //在集合的第一个位置添加指定元素
addLast(Object o) //在集合的最后一个位置添加指定元素
//删除方法:
removeFirst() //删除集合中的第一个元素
removeLast() //删除集合中的最后一个元素

下面程序简单的创建了两个链表,将它们合并在一起,然后从第二个链表中每隔一个元素删除一个元素,最后测试removeAll()方 法 :

package listdemo;import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;public class LinkedListTest {public static void main(String[] args) {List<String> a = new LinkedList<>();a.add("aaa");a.add("bbb");a.add("eee");List<String> b = new LinkedList<>();b.add("AAA");b.add("BBB");b.add("EEE");ListIterator<String> aIter = a.listIterator();ListIterator<String> bIter = b.listIterator();//a集合合并b集合while(bIter.hasNext()) {if(aIter.hasNext())aIter.next();aIter.add(bIter.next());}System.out.println(a);//从b链表中每间隔一个元素删除一个元素while(bIter.hasNext()) {bIter.next();//跳过一个元素if(bIter.hasNext()) {bIter.next();bIter.remove();//先查后删}}System.out.println(b);//测试删除所有a.removeAll(a);System.out.println(a);}
}

五:最后来看看ArrayList与LinkedList的区别

  • 1. 是否保证线程安全: ArrayListLinkedList 都是不同步的,也就是不保证线程安全;

  • 2. 底层数据结构: Arraylist 底层使用的是 Object 数组LinkedList 底层使用的是 双向链表 数据结构(JDK1.6之前为循环链表,JDK1.7取消了循环。注意双向链表和双向循环链表的区别,下面有介绍到!)

  • 3. 插入和删除是否受元素位置的影响:ArrayList 采用数组存储,所以插入和删除元素的时间复杂度受元素位置的影响。 比如:执行add(E e) 方法的时候, ArrayList 会默认在将指定的元素追加到此列表的末尾,这种情况时间复杂度就是O(1)。但是如果要在指定位置 i 插入和删除元素的话(add(int index, E element) )时间复杂度就为 O(n-i)。因为在进行上述操作的时候集合中第 i 和第 i 个元素之后的(n-i)个元素都要执行向后位/向前移一位的操作。 ② LinkedList 采用链表存储,所以插入,删除元素时间复杂度不受元素位置的影响,都是近似 O(1)而数组为近似 O(n)。

  • 4. 是否支持快速随机访问: LinkedList 不支持高效的随机元素访问,而 ArrayList 支持。快速随机访问就是通过元素的序号快速获取元素对象(对应于get(int index) 方法)。

  •         5. 内存空间占用: ArrayList的空 间浪费主要体现在在list列表的结尾会预留一定的容量空间,而LinkedList的空间花费则体   现在它的每一个元素都需要消耗比ArrayList更多的空间(因为要存放直接后继和直接前驱以及数据)。

推荐阅读:

  • 集合详解之Set
  • Java集合详解之Map
  • Java集合之并发容器

参考引用:

  1. java核心思想
  2. Java集合框架常见面试题
  3. Java中的Collection集合接口常用方法

程序员应该吃透的集合List相关推荐

  1. 微信小程序时代,小程序员的产品创意集合

    微信小程序,一个新的时代即将来临,在微信公众号时代,玩的是文字能力,在微信小程序(应用号)时代玩的是技术能力. "好玩+有用+互动+分享"将是未来微信小程序商业模式的主要方向,好奇 ...

  2. 黑马程序员java学习日记——集合框架

    ------- android培训.java培训.期待与您交流! ---------- Java.util包中提供了一些集合类,这些集合类又被称为容器.集合类与数组的不同之处是,数组长度是固定的,集合 ...

  3. 黑马程序员----------------java基础-----------------Map集合

     ------- <a href="http://www.itheima.com" target="blank">android培训</a ...

  4. 程序员常用资源工具集合【建议收藏】

    点击上方"杰哥的IT之旅",选择"置顶公众号" 干货.福利第一时间送达! CSDN海量资源免费下载! 搜索资源网站 学习技术过程我们经常需要使用搜索引擎来检索资 ...

  5. 程序员网页版工具集合

    Overview 本文主要收集一下作为程序员经常会用到的一些小工具网站 crontab表达式 https://tool.lu/crontab/ struct和json互转 https://json2s ...

  6. 中国程序员经典名言大集合

    1.都快被你搞死了.    前任杂乱无章的代码,客户不断变更的需求,把你搞得头晕脑涨的时候,你能怎么说?  2.我快要疯掉了.    病毒,木马,盗版软件,当你花了三天时间也装不上系统的时候,恐怕只能 ...

  7. BAT程序员常用的工具集合!

    这里写目录标题 阿里篇 腾讯篇 百度篇 推荐的仅供大家参考,工具大部分为开源项目,大家可以按需选用 阿里篇 一.Java 线上诊断工具 ArthasArthas 是阿里巴巴 2018 年 9 月开源的 ...

  8. 黑马程序员 Java基础——List集合

    ------- <a href="http://www.itheima.com" target="blank">android培训</a> ...

  9. Java 程序员常用资源工具集合

    本文章转载自微信公众号:JAVA 学习技术过程我们经常需要使用搜索引擎来检索资料,国内常用的也就是某度了. 当然有条件的话,搜索引擎首先还是推荐使用 Google,如果没办法使用,可以使用以下几个作为 ...

最新文章

  1. 红黑树 键值_查找(一)史上最简单清晰的红黑树讲解
  2. keyshot分辨率多少合适_惠普打印机型号有哪些 惠普打印机多少钱【详解】
  3. Py之GUI之PyQt:PyQt5的简介、入门、安装(QtCreator和QtDesigner)图文教程之详细攻略
  4. 【温故知新】CSS学习笔记(盒子内边距介绍)
  5. AKKA框架持久化入门样例
  6. 电脑重装系统后提示invalid partition table怎么解决
  7. ActionContextCleanUp作用
  8. Mybatis逆向工程自动生成代码文件
  9. 机器学习实战——KNN及部分函数注解
  10. linux中文输入法怎么安装目录,Linux怎么安装中文输入法
  11. 物联网中间件的未来是云计算技术为中心和混合结构
  12. github-新建文件夹
  13. embarrass的用法和搭配_embarrass_embarrass的意思和用法搭配
  14. windows安装exe为系统服务
  15. 旷视科技19届春招:算法研究员面经
  16. CUPS学习五:打印机基础
  17. Python 英文的月份转数字及数字转英文
  18. 利用windows 系统的画图工具获取图片上某一点的颜色RGB值
  19. 输入字体之间的间隔突然变大了
  20. 京东API—获取京东商品详情

热门文章

  1. Redis 笔记(07)— sorted set 类型(添加、删除有序集合元素、获取分数范围内成员、按score排序、返回集合元素个数)
  2. Go 学习笔记(82)— Go 第三方库之 viper(解析配置文件、热更新配置文件)
  3. 那些年值得铭记的时刻
  4. Ubuntu更换阿里源以及由于没有公钥,无法验证下列签名错误
  5. IDEA : Git Pull Failed 解决(IDEA中使用stash功能)
  6. 网络安全工具:Wireshark
  7. Golang的交叉编译问题
  8. Yolov1目标检测算法详细分析
  9. centos7 安装 Mysql 5.7.28,详细完整教程
  10. 量子力学在计算机上的应用,量子力学在医学科学中的应用