JavaSE中Collection集合框架学习笔记(1)——具有索引的List
前言:因为最近要重新找工作,Collection(集合)是面试中出现频率非常高的基础考察点,所以好好恶补了一番。
复习过程中深感之前的学习不系统,而且不能再像刚毕业那样死背面试题,例如:String是固定长度的,StringBuffer和StringBuilder的长度是可以变化的。如果一旦问得深入一点,问为什么有这样的区别就傻眼了,只能一脸呆萌地看着面试官。
因此想要通过写文章的形式,系统地总结学习的内容,例如Collection架构是怎样的、有哪些相关的继承和接口实现,这样才能了解什么时候应该用哪个类,以及类之间要如何搭配合作,才知道出了问题应该如何解决。这一系列文章适用于Java技术岗的应聘者、高校计算机专业的学生以及培训机构学习Java的初学者阅读。
1.1 认识Collection架构
我们都使用过ArrayList类收集对象,例如add()方法新增对象,remove()方法移除对象,这些都不会陌生。但是这些方法是怎么来的呢?下图是该类的继承架构图:

ArrayList一个类就这么复杂,如果要把全部Collection架构表现在一张图上,那估计就跟蜘蛛网一样纠缠不清。简化一下,忽略一些不那么重要的接口和实现类,我们可以得到以下这张架构图。

从图上可知,Colletion是一个接口,实现了另一个接口Iterable。Collection下面有三个接口直接实现了它,分别是List、Set和Queue。List下面有两个实现类,分别是ArrayList和LinkedList;Set的常用实现类是TreeSet和HashSet;Queue下面有Deque接口实现,再下面是实现类ArrayDeque.
这张图将会是这一系列文章的核心,之后会反复提及,不妨称之为Collection架构图,每一篇文章都是介绍其中的一部分。熟悉这张图,不仅有助于理解学习,还可以帮助记忆。至于详细周全的继承关系和实现架构,到底有哪些类实现了哪些接口、继承了哪些类,可以自行在API说明文档中查询。
1.2 具有索引的List
List实现了Collection接口,所以我们可以说List是一种Colletion,作用就是收集对象,特点是以索引的方式记录所收集的对象顺序。List中常见的实现类是刚才所提及架构图中的ArrayList,忘了的读者可以翻到前面对照着看。
/**
* ArrayList的实验用例
*/ import java.util.*; public class Student {
public static void main(String[] args) {
List list = new ArrayList(); //使用JavaSE的List和ArrayList
Scanner scanner = new Scanner(System.in);
String name;
while(true) {
System.out.print("学生签到:");
name = scanner.nextLine();
if(name.equals("quit")) {
break;
}
list.add(name); //实用Add()方法收集对象
}
System.out.println("今天上来上课的学生名单:");
foreach(list);
} private static void foreach(List list) {
for(int i = 0; i < list.size(); i++) {
String student = (String) list.get(i); //使用get()方法依据索引取得收集的对象
System.out.println(student);
}
}
}
以上是ArrayList类的一个简单使用例子,模拟的是学生上课签到的情景。强烈建议读者跟我一样自己试着写一个简单用例,尤其是之前很少使用ArrayList的初学者,单纯的看和读跟实际敲代码产生的效果完全不一样。也可以照着我给出的例子敲,偷懒一点的话可以直接复制在机器上跑一遍。

从Collection架构图中可知,LinkedList同样也实现了List接口。就算只是把上面那个实验中的ArrayList全部改为LinkedList,程序照样可以运作,而且效果看起来完全相同。那么问题来了,我们什么时候应该使用ArrayList,什么时候又应该使用LinkedList呢?
1.2.1 ArrayList的特性
卡车和轮船都可以运送货物,我们可以根据不同的情况选择不同的运输方式。如果时间紧、运输量小,而且两个地点都在陆地上(例如北京到南京),那么我们可以使用汽车;如果时间多、运输量大,出发地和目的之间隔着海洋(例如大连到纽约),那么用船运是更好的选择。
刚毕业那会要找工作,为了面试背过“ArrayList像数组,读取速度快,但是需要调整索引的话表现很差;LinkedList像链表,调整索引的表现非常好,但是随机读取的速度比较慢”。那么我们可以问深一句,为什么会这样呢?不妨从源代码中找寻答案。
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
上面这一段是JavaSE的源代码,我们可以看到ArrayList中的add()方法非常简单,跟我们平时使用数组一样。查看源代码中更多内容你会发现,ArrayList内部就是使用Object数组来保存所收集的对象,这就是为什么说“ArrayList就像数组”的原因。在考虑是否使用ArrayList的时候,我们可以相当于考虑是否要使用数组的特性。
1.2.2 LinkedList的特性
在学习Collection架构的时候,我们不妨可以多看源代码,看的时候优先比较几个基本方法的实现,例如add()、remove()等。从这些方法的实现,我们就可以看到不同实现类的特性。
public boolean add(E e) {
linkLast(e);
return true;
}
/**
* Links e as last element.
*/
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
看到LinkdedList.add()的源代码,我们会发现其实现方式跟链表的实现如出一辙。如果last结点为null,那么说明链表为空,所以新添加的结点为头结点。如果last结点不等于null,那么把新添加的结点设为last的下一个结点,作为新的尾结点。
根据链表的特性,我们可以很快总结两点点特性:1.想要指定索引随机存取时,链接方式都得使用从第一个元素开始查找下一个元素的方式,效率比较糟糕;2.链接的每个元素都会参考下一个元素,这有利于调整索引顺序。
1.2.3 List总结
作为Collection三大阵营之一的List,最大的特点就是索引,我们可以通过索引做到随机存取。
List中常用的实现有ArrayList和LinkedList,各自的特性可以分别参考数组和链表。在比较它们之间区别的过程中,我们看了源代码,提倡在比较同一接口不同实现类时重点查看它们共同需要实现的方法,例如Collection中规定的add(),remove()等。
面试中常见的List实现类其实还有Vector,其特性与ArrayList相同。不同在于Vector具有线程安全的特性,性能开销比较大,具体的内容会放在以后关于多线程的文章里。
在总结过程中,给初学者提供两个建议,一是做实验,通过写一些demo来熟悉所学内容;二是在力所能及的情况下多看源代码,知其然也要知其所以然。
如果你喜欢我的文章,可以扫描关注我的个人公众号“李文业的思考笔记”。
不定期地会推送我的原创思考文章。

JavaSE中Collection集合框架学习笔记(1)——具有索引的List的更多相关文章
- JavaSE中Collection集合框架学习笔记(2)——拒绝重复内容的Set和支持队列操作的Queue
前言:俗话说“金三银四铜五”,不知道我要在这段时间找工作会不会很艰难.不管了,工作三年之后就当给自己放个暑假. 面试当中Collection(集合)是基础重点.我在网上看了几篇讲Collection的 ...
- JavaSE中Collection集合框架学习笔记(3)——遍历对象的Iterator和收集对象后的排序
前言:暑期应该开始了,因为小区对面的小学这两天早上都没有像以往那样一到七八点钟就人声喧闹.车水马龙. 前两篇文章介绍了Collection框架的主要接口和常用类,例如List.Set.Queue,和A ...
- Java集合框架学习笔记
集合类的由来:对象用于封装特有数据,对象多了需要存储,如果对象的长度不确定,就使用集合存储. 集合特点1.用于存储对象的容器.2.集合的长度可变.3.集合中不可以存储基本类型 集合容器因为内部的数据结 ...
- 集合框架学习笔记<二>
1.什么是ArrayList ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处: 动态的增加和减少元素 实现了ICollection和ILis ...
- 集合框架学习笔记<三>
一些重要的区别 set与list的区别: set是无索引的,list是有索引的: ArrayList与LinkList的区别: 前者是基于数组实现的,后者是基于链表实现的: 两者的使用方法一样,但是在 ...
- JavaSE中Map框架学习笔记
前言:最近几天都在生病,退烧之后身体虚弱.头疼.在床上躺了几天,什么事情都干不了.接下来这段时间,要好好加快进度才好. 前面用了三篇文章的篇幅学习了Collection框架的相关内容,而Map框架相对 ...
- JavaSE中线程与并行API框架学习笔记1——线程是什么?
前言:虽然工作了三年,但是几乎没有使用到多线程之类的内容.这其实是工作与学习的矛盾.我们在公司上班,很多时候都只是在处理业务代码,很少接触底层技术. 可是你不可能一辈子都写业务代码,而且跳槽之后新单位 ...
- JavaSE中线程与并行API框架学习笔记——线程为什么会不安全?
前言:休整一个多月之后,终于开始投简历了.这段时间休息了一阵子,又病了几天,真正用来复习准备的时间其实并不多.说实话,心里不是非常有底气. 这可能是学生时代遗留的思维惯性--总想着做好万全准备才去做事 ...
- Yii框架学习笔记(二)将html前端模板整合到框架中
选择Yii 2.0版本框架的7个理由 http://blog.chedushi.com/archives/8988 刚接触Yii谈一下对Yii框架的看法和感受 http://bbs.csdn.net/ ...
随机推荐
- Linux学习第一步(虚拟机的和镜像文件的安装)
一.安装虚拟机(本文以vmware workstation 12为例) 1.在网上所有虚拟机并下载. 2.找到下载文件安装好 3.一直下一步 4.接下来的就是选择安装的目录了,当然如果你的电脑c盘够大 ...
- Java并发编程:Callable、Future和FutureTask的实现
启动线程执行任务,如果需要在任务执行完毕之后得到任务执行结果,可以使用从Java 1.5开始提供的Callable和Future 下面就分析一下Callable.Future以及FutureTask的 ...
- VR全景智慧城市
随着虚拟现实产业的发展,我国对虚拟现实产业也越来越重视了.我国虚拟现实VR市场增长速度很快,市场活跃性很高,很多人都看好我国的虚拟现实VR市场,而且未来国内虚拟现实VR市场的销量还将有更大的增长.据赛 ...
- New Adventure----GUI Design Studio
新建项目工程 File->New Project 新建设计文件 Project->New Design 单个设计文件的页面,F9运当前设计页面 页面控件中有绿色包围的控件为 ...
- 当KDS晶振遇上爱普生晶振国内生产厂家该如何抉择?
当KDS晶振遇上爱普生晶振国内生产厂家该如何抉择? 全球做晶振行业的公司有很多,单说深圳一个城市就有几十上百家正规的晶振厂家,深圳市金洛电子就是其中之一.我们不光代理日本和台湾多家排得上名 ...
- 2017 UESTC Training for Graph Theory
图论姿势太弱,这套题做了好久.. A:枚举最短那条边,然后最小生成树那种操作,1 和 n 联通就算答案 B:考虑到假如我们能凑出x的话,那很明显我们也能凑出任意数表示x + ai,考虑选取一个ai,然 ...
- iOS面试题及答案
设计模式是什么? 你知道哪些设计模式,并简要叙述? 设计模式是一种编码经验,就是用比较成熟的逻辑去处理某一种类型的事情. 1). MVC模式:Model View Control,把模型 视图 控制器 ...
- 【Netty】Netty之ByteBuf
一.前言 前面已经学习了Netty中传输部分,现在接着学习Netty中的ByteBuf. 二.ByteBuf 2.1 ByteBuf API 在网络上传输的数据形式为Byte,Java NIO提供了B ...
- C#控制台或应用程序中两个多个Main()方法的可行性方案
大多数初级程序员或学生都认为在C#控制台或应用程序中只能有一个Main()方法.但是事实上是可以有多个Main()方法的. 在C#控制台或应用程序中,在多个类中,且每个类里最多只能存在一个Main() ...
- (数字IC)低功耗设计入门(五)——RTL级低功耗设计(续)
二.RTL级低功耗设计(续) 前面一篇博文我记录了操作数隔离等低功耗设计,这里就主要介绍一下使用门控时钟进行低功耗设计. (4)门控时钟 门控时钟在我的第一篇博客中有简单的描述,这里就进行比较详细的描 ...