博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java集合——Collection接口以及ArrayList,Vector,LinkedList的源码剖析——最认真的图解——第一章
阅读量:3959 次
发布时间:2019-05-24

本文共 10744 字,大约阅读时间需要 35 分钟。

文章目录

1:集合体系图

Collection:单列集合,该接口有两个重要的子接口List Set,他们的实现子类都是单列集合

在这里插入图片描述
Map:双列集合,Map接口的实现子类,存放K-V
在这里插入图片描述

2:Collection方法

2.1 Collection接口和常用方法

  • Collection接口实现类的特点
public interface Collection< E > extends Iterable < E >

1 ) collection实现子类可以存放多个元素, 每个元素可以是Object

2)有些Collection的实现类,可以存放重复的元素,有些不可以

3)有些Collection的实现类,有些是有序的(List), 有些不是有序(Set)

4) Collection接口没有直接的实现子类,是通过它的子接口Set和List来实现的

在这里插入图片描述

  • Collection接口常用方法,以实现子类ArrayList来演示。CollectionMethod.java
1) add:添加单个元素2) remove:删除指定元素3) contains:查找元素是否存在4) size:获取元素个数5) isEmpty:判断是否为空6) clear:清空7) addAll:添加多个元素8) containsAll:查找多个元素是否都存在9) removeAll:删除多个元素
public class CollectionMethod {
public static void main(String[] args) {
List list=new ArrayList();// 1) add:添加单个元素 list.add("zlj"); list.add(10); list.add(true);// 2) remove:删除指定元素 list.remove(1); System.out.println("list:"+list);// 3) contains:查找元素是否存在 System.out.println(list.contains(true));// 4) size:获取元素个数 System.out.println(list.size());// 5) isEmpty:判断是否为空 System.out.println(list.isEmpty());// 6) clear:清空 list.clear(); System.out.println("list:"+list);// 7) addAll:添加多个元素 ArrayList list2=new ArrayList(); list2.add("西游记"); list2.add("水浒传"); list.addAll(list2);// 8) containsAll:查找多个元素是否都存在 list.containsAll(list2);// 9) removeAll:删除多个元素 list.add("java虚拟机"); list.removeAll(list2); System.out.println("list:"+list); } }

2.2 Collection接口遍历元素的方式

2.2.1 使用Iterator(迭代器)基本介绍

在这里插入图片描述

  1. Iterator对象称为迭代器,主要用于遍历Collection集合中的元素。2)所有实现了Collection接口的集合类都有一个iterator(0方法, 用以返回一个实现了Iterator接口的对象, 即可以返回一个迭代器。

  2. Iterator的结构

    在这里插入图片描述
    注意:在调用iterator.next()方法之前必须要调用iterator.hasNext()进行检测。若不调用,且下一条记录无效,直接调用iterator.next()会抛出NoSuchElementException异常。如果希望再次遍历,需要我们重置一个迭代器

  3. Iterator仅用于遍历集合, Iterator本身并不存放对象。

实例演示

public class CollectionIterator {
public static void main(String[] args) {
List list=new ArrayList(); list.add(new Book("java虚拟机","300")); list.add(new Book("java规范","100")); list.add(new Book("Spring","200")); //1:先得到list对于的迭代器 Iterator iterator = list.iterator(); //2:使用while循环遍历,判断是否还有数据 while (iterator.hasNext()){
//3:返回下一个元素 System.out.println(iterator.next()); } }}class Book{
private String name; private String price; @Override public String toString() {
return "Book{" + "name='" + name + '\'' + ", price='" + price + '\'' + '}'; } public Book(String name, String price) {
this.name = name; this.price = price; }}

2.2.2 for循环增强

增强for循环(底层仍然是iterator迭代器),可以代替iterator迭代器,特点:增强for就是简化版的iterator,本质一样。只能用于遍历集合或数组。for循环增强也可以在数组中使用

基本语法

for(元素类型元素名:集合名或数组名){
访问元素
}

实例演示:如上代码的iterator改成for循环增强即可

//..        for (Object book:list){
System.out.println("book="+book); } //...
book=Book{name='java虚拟机', price='300'}book=Book{name='java规范', price='100'}book=Book{name='Spring', price='200'}

3:List接口和方法

3.1 List接口基本介绍

在这里插入图片描述

常用的有ArrayList,LinkedList,Vector

List接口是Collection接口的子接口

  1. List集合类中元素有序(即添加顺序和取出顺序一致)、 且可重复,

  2. List集合中的每个元素都有其对应的顺序索引,即支持索引。

  3. List容器中的元素都对应一 个整数型的序号记载其在容器中的位置, 可以根据序号存取容器中的元素。

    案例演示

public class ListMethod {
public static void main(String[] args) {
// List集合类中元素有序(即添加顺序和取出顺序一致)、 且可重复, List list=new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(3); System.out.println("list="+list);//List集合中的每个元素都有其对应的顺序索引,即支持索引。 System.out.println(list.get(3)); }}
list=[1, 2, 3, 3]3

3.2 List接口的常用方法

List集合里添加了一些根据索引来操作集合元素的方法

  1. void add(int index, Object ele):在index位置插入ele元素

  2. boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来

  3. Object get(int index):获取指定index位置的元素

  4. int indexOf(Object obj):返回obj在集合中首次出现的位置

  5. int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置

  6. Object remove(int index):移除指定index位置的元素,并返回此元素

  7. Object set(int index, Object ele):设置指定index位置的元素为ele ,相当于是替换.

  8. List subList(int fromIndex, int tolndex):返回从fromIndex到tolndex位置的子集合

    案例演示

public class ListMethod {
public static void main(String[] args) {
// List集合类中元素有序(即添加顺序和取出顺序一致)、 且可重复, List list=new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(3); System.out.println("list="+list);//List集合中的每个元素都有其对应的顺序索引,即支持索引。 System.out.println(list.get(3));// 1) void add(int index, Object ele):在index位置插入ele元素 list.add(1,"java"); System.out.println("list="+list);// 2) boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来 List list2= new ArrayList(); list2.add("男"); list2.add("女"); list.addAll(1,list2); System.out.println("list="+list);// 3) Object get(int index):获取指定index位置的元素 System.out.println( list.get(1));//// 4) int indexOf(Object obj):返回obj在集合中首次出现的位置 System.out.println(list.indexOf(3));// 5) int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置 System.out.println(list.lastIndexOf(3));// 6) Object remove(int index):移除指定index位置的元素,并返回此元素 list.remove(0); System.out.println("list="+list);// 7) Object set(int index, Object ele):设置指定index位置的元素为ele ,相当于是替换. list.set(0,"man"); System.out.println("list="+list);// 8) List subList(int fromIndex, int tolndex):返回从fromIndex到tolndex位置的子集合 System.out.println(list.subList(0,3)); }}

3.3 List接口的三种遍历方式

  1. 迭代器
  2. 增强for循环
  3. 使用普通for循环
    案例演示
public class ListFor {
public static void main(String[] args) {
List list=new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(3); //1.迭代器 System.out.println("======迭代器======="); Iterator iterator = list.iterator(); while (iterator.hasNext()) {
Object next = iterator.next(); System.out.println(next); } System.out.println("======增强for循环======="); for (Object object:list){
System.out.println(object); } System.out.println("======普通for循环======="); for (int i=0;i

4:ArrayList源码剖析

ArrayList的注意事项

  1. ArrayList可以加入null,并且加多个

  2. ArrayList是由数组来实现数据存储的

  3. ArrayList基本等同于Vector ,除了ArrayList是线程不安全(执行效率高)看源码,在多线程情况下,不建议使用ArrayList

ArrayList的底层操作机制源码分析(重点,难点)

先说结论在分析源码
1 ) ArrayList中维护了一个Object类型的数组elementData

transient Object[] elementData//transient 表示短暂的,瞬间,表示该属性不会被序列化

2)当创建对象时,如果使用的是无参构造器,则初始elementData容量为0 (jdk7是10)

3)当添加元素时:先判断是否需要扩容,如果需要扩容,则调用grow方法,否则直接添加元素到合适位置

4)如果使用的是无参构造器,如果第一次添加,需要扩容的话,则扩容elementData为10,如果需要再次扩容的话,则扩容elementData为1.5倍。

5)如果使用的是指定容量capacity的构造器,则初始elementData容量为capacity

6)如果使用的是指定容量capacity的构造器,如果需要扩容,则直接扩容elementData为1.5倍。

当创建对象时,如果使用的是无参构造器案例演示

public class ArrayListSource {
public static void main(String[] args) {
//解读源码 //使用无参构造器创建ArrayList对象 ArrayList arrayList=new ArrayList(); //使用for循环给list添加1-10数据 for (int i=0;i<=10;i++){
arrayList.add(i); } //使用for循环给list添加11-15数据 for (int i=11;i<=15;i++){
arrayList.add(i); } //使用for循环给list添加16,17,18数据 arrayList.add(100); arrayList.add(200); arrayList.add(null); }}

源码剖析

Debug
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
当创建对象时,如果使用的是有参构造器案例演示
源码剖析
Debug
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

5:Vector源码剖析

Vector注意事项

1)Vector类的定义说明
在这里插入图片描述
2) Vector底层也是一个对象数组

protected Object[] elementData;

3 ) Vector是线程同步的,即线程安全,Vector类的操作方法带有synchronized

public synchronized E get(int index) {
if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index); return elementData(index); }

4)在开发中需要线程同步安全时,需要考虑使用Vector

案例演示

public class VectorSource {
public static void main(String[] args) {
//无参构造器 Vector objects = new Vector<>(); for (int i=0;i<10;i++){
objects.add(i); } }}

源码剖析

Debug
在这里插入图片描述

6:LinkedList源码剖析

6.1 LinkedList的全面说明和底层操作机制

全面说明

1 ) LinkedList底层实现了双向链表和双端队列特点
2 )可以添加任意元素(元素可以重复),包括null
3 )线程不安全,没有实现同步

LinkedList的底层操作机制

1 ) LinkedList底层维护了一个双向链表.

2 ) LinkedList中维护了两个属性first和last分别指向首节点和尾节点

3)每个节点(Node对象) ,里面又维护了prev、next、 item三个属性,其中通过prev指向前一个,通过next指向后一个节点。最终实现双向链表.

4)所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高。

在这里插入图片描述
模拟双向链表遍历

public class LinkedListDemo {
public static void main(String[] args) {
//模拟一个简单的双向链表 Node zlj = new Node("zlj"); Node zzg = new Node("zzg"); Node lqx = new Node("lqx"); //连接三个节点,形成双向链表 //zlj->zzg->lqx zlj.next=zzg; zzg.next=lqx; //lqx->zzg->zlj lqx.pre=zzg; zzg.pre=zlj; Node first=zlj;//first引用指向zlj,就是双向链表的头节点 Node last=lqx;//last引用指向lqx,就是双向链表的尾节点 //从头到尾进行遍历 System.out.println("============从头到尾进行遍历============"); while (true){
if (first==null) {
break; } System.out.println(first); first=first.next; } //从尾到头进行遍历 System.out.println("============从尾到头进行遍历=============="); while (true){
if (last==null){
break; } System.out.println(last); last=last.pre; } }}//定义一个Node类,Node对象,表示双向链表的一个节点class Node{
public Object item;//真正存放数据 public Node next;//指向后一个节点 public Node pre;//指向前一个结点 public Node(Object name){
this.item=name; } @Override public String toString() {
return "Node{" + "item=" + item + '}'; }}
============从头到尾进行遍历============Node{item=zlj}Node{item=zzg}Node{item=lqx}============从尾到头进行遍历==============Node{item=lqx}Node{item=zzg}Node{item=zlj}

模拟双向链表的添加和删除(主要代码和上面一样)

//....        //演示链表添加对象        Node node = new Node("添加元素");        zlj.next=node;        node.next=zzg;        zzg.pre=node;        node.pre=zlj;        //..
============从头到尾进行遍历============Node{item=zlj}Node{item=添加元素}Node{item=zzg}Node{item=lqx}
/...        //演示链表添加对象        Node node = new Node("添加元素");        zlj.next=node;        node.next=zzg;        zzg.pre=node;        node.pre=zlj;        //演示链表删除对象        zlj.next=zzg;        zzg.pre=zlj;        //..
============从头到尾进行遍历============Node{item=zlj}Node{item=zzg}Node{item=lqx}

6.2 LinkedList源码剖析

linkedList 的add方法源码剖析

public class LinkedListCRUDSource {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList(); linkedList.add(1); linkedList.add(2); System.out.println("linkedList="+linkedList); }}

在这里插入图片描述

7:List实现类的选择

在这里插入图片描述

在这里插入图片描述
如何选择ArrayList和LinkedList:

1)如果我们改查的操作多,选择ArrayList

2)如果我们增删的操作多,选择LinkedList

3)一般来说,在程序中,80%-90%都是查询,因此大部分情况下会选择ArrayList

4)在一个项目中,根据业务灵活选择,也可能这样,一个模块使用的是ArrayList,另外一个模块是LinkedList.

转载地址:http://srozi.baihongyu.com/

你可能感兴趣的文章
urllib2.urlopen超时问题
查看>>
Choosing a Machine Learning Classifier
查看>>
魏兴国:深入浅出DDoS攻击防御
查看>>
使连续的参考文献能够中间用破折号连起来
查看>>
Discover Feature Engineering, How to Engineer Features and How to Get Good at It
查看>>
36辆车,6条跑道,无计时器,最少几次比赛可以选出前三
查看>>
matlab2012b与matlab7.1执行set(gca,'Yscale','log')之后画到的直方图结果居然不同
查看>>
python读大文件
查看>>
python 3里没有cmp这个函数了
查看>>
回文题
查看>>
二叉树的最短根到叶路径中点的个数
查看>>
给定二叉树求最小深度
查看>>
平衡树
查看>>
栈的应用题(1)
查看>>
判断链表是否有环
查看>>
从有序链表中去掉重复的
查看>>
后台程序结果重定向到文件,结果看不到文件?缓冲区的问题
查看>>
[LeetCode]Reverse Integer
查看>>
DNS采用的传输层协议可能是TCP或UDP
查看>>
Python SocketAPI
查看>>