Java初学笔记18-【集合、Collection接口、List接口、ArrayList类、Vector类、LinkedList类、迭代器】

Java初学笔记18

【难点】
1.理解集合的底层机制
2.阅读原码
3.何时使用何种集合
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

一、 集合介绍

  1. 保存多个数据使用的是数组,那么数组有不足的地方
    (1)长度开始时必须指定,而且一旦指定,不能更改;
    (2)保存的必须为同一类型的元素;
    (3)使用数组进行增加/删除元素,比较麻烦;
    (4)数组扩容比较麻烦

  2. 故引出----->集合
    (1)可以动态保存任意多个对象,使用比较方便!
    (2)提供了一系列方便的操作对象的方法: add、remove、set、get等
    (3)使用集合添加,删除新元素更简洁了

二、集合的框架体系

Java 的集合很多,主要分为两大组:
Collection单列集合 与 Map双列集合。

  1. Collection 单列集合(存放单个对象)
    (1)Collection 接口有两个重要的子接口 ListSet , 他们的实现子类都是单列集合
    在这里插入图片描述

  2. Map 双列集合(存放键值对)
    (1)Map 接口的实现子类 是双列集合,存放的 K-V
    在这里插入图片描述

三、Collection接口

1. Collection接口实现类的特点

(1)Collection接口:
public interface Collection extends Iterable
(2)collection实现子类可以存放多个元素,每个元素可以是Object
(3)有些Collection的实现类,可以存放重复的元素,有些不可以
(4)有些Collection的实现类,有些是有序的(List),有些不是有序(Set)
(5)Collection接口没有直接的实现子类,是通过它的子接口Set和 List来实现的

2. Collection接口里面的方法

【以ArrayList类为例演示方法:public class ArrayList extends AbstractList implements List, RandomAccess, Cloneable, java.io.Serializable】

List list = new ArrayList()

(1)add:添加单个元素

list.add("jack");
list.add(10);//实际上为list.add(new Integer(10))
list.add(true);

(2)remove:删除指定元素

list.remove(0);  //删除第一个元素
list.remove(true);//指定删除某个元素

删除的时候也是要计算hashcode。如果人为的更改了hashcode,将会删除失败!!在这里插入图片描述

(3)contains:查找元素是否存在

System.out.println(list.contains("jack"));//T

(4)size:获取元素个数

System.out.println(list.size()); //2

(5)isEmpty:判断是否为空

System.out.println(list.isEmpty());//F

(6)clear:清空

list.clear();

(7)addAll:添加多个元素

ArrayList list2 = new ArrayList();
list2.add("红楼梦");
list2.add("三国演义");
list.addAll(list2);

(8)containsAll:查找多个元素是否都存在

System.out.println(list.containsAll(list2));//T

(9)removeAll:删除多个元素

list.add("聊斋");
list.removeAll(list2);
System.out.println("list=" + list);  //[聊斋]

3. Collection接口遍历元素方式1–>使用Iterator(迭代器)

(1)Iterable接口中,有一个可以返回Iterator接口类型的方法iterator()。iterator()对象称为迭代器,主要用于遍历Collection集合中的元素
在这里插入图片描述

(2)Iterator接口中有几个方法:

1)boolean hasNext();//判断是否还有下一个元素
2)E next(); //①指针下移②将下移以后集合位置上的元素返回

注意:在调用iterator.next()方法之前必须要调用iterator.hasNext()进行检测。若不调用,且下一条记录无效,直接调用iterator.next()会抛出NoSuchElementException异常。

在这里插入图片描述

(3)所有实现了Collection接口的集合类都有一个iterator()方法,该方法返回一个实现了lterator接口的对象,即可以返回一个迭代器。
(4)Iterator仅用于遍历集合,Iterator本身并不存放对象。
(5)迭代器配合while循环、hasnext()方法、next()方法使用,且hasnext()方法必须在next()方法之前使用,此外当迭代器移动到最后一个位置时候,要想重新遍历,需要重置迭代器

(6)代码示例

接口类型的变量col 可以指向实现了Collection接口类的对象实例

Collection col = new ArrayList();
        col.add(new Book("三国演义", "罗贯中", 10.1));
        col.add(new Book("小李飞刀", "古龙", 5.1));
        col.add(new Book("红楼梦", "曹雪芹", 34.6));
		//System.out.println("col=" + col);
		//现在希望能够遍历 col 集合
		1. 先得到 col 对应的 迭代器
        Iterator iterator = col.iterator();
		2. 使用 while 循环遍历
		// while (iterator.hasNext()) {//判断是否还有数据
		// //返回下一个元素,类型是 Object
		// Object obj = iterator.next();
		// System.out.println("obj=" + obj);
		// }
		//快捷键,快速生成 while => itit
		//显示所有的快捷键的的快捷键 ctrl + j
        while (iterator.hasNext()) {
            Object obj = iterator.next();
            System.out.println("obj=" + obj)
        }
		//3. 当退出 while 循环后 , 这时 iterator 迭代器,指向最后的元素
		// iterator.next();//NoSuchElementException
		//4. 如果希望再次遍历,需要重置我们的迭代器
        iterator = col.iterator();
        System.out.println("===第二次遍历===");
        while (iterator.hasNext()) {
            Object obj = iterator.next();
            System.out.println("obj=" + obj);
        }

(7)快捷键

快捷键,快速生成 while ,用 itit
显示所有的快捷键的的快捷键 ,用ctrl + j
for循环增强,用I

4. Collection接口遍历元素方式2–>for循环增强

(1)简化版的Iterator
(2)快捷键:for循环增强,I
(3)代码示例:

for (Object object : col){
        System.out.println(object);
}

【迭代器练习题】
在这里插入图片描述

四、List接口

1. 介绍

(1)List接口是Collection 接口的子接口
(2)List集合类中元素有序(即添加顺序和取出顺序一致)、且元素可重复
(3)List集合中的每个元素都有其对应的顺序索引,即支持索引。索引从0开始。
(4)List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。

2. 常用方法

List list = new ArrayList();
list.add("张三丰");
list.add("贾宝玉");

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

在 index = 1 的位置插入一个对象
list.add(1, "大志");

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

List list2 = new ArrayList();
list2.add("jack");
list2.add("tom");
list.addAll(1, list2);

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

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

System.out.println(list.indexOf("tom"));//2

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

list.add("大志");
System.out.println(list.lastIndexOf("大志"));

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

list.remove(0);

(7)Object set(int index, Object ele):设置指定 index 位置的元素为 ele

相当于是替换
list.set(1, "玛丽");

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

注意 [ fromIndex, toIndex )

List returnlist = list.subList(0, 2); // [ 0 , 2 )

在这里插入图片描述

五、ArrayList类

1. 介绍

(1)“permits all elements, including null" ArrayList可以加入null,并且多个
(2)ArrayList是由数组来实现数据存储的
(3)ArrayList基本等同于Vector,除了 ArrayList是线程不安全(执行效率高),在多线程情况下,不建议使用ArrayList。

2. ArrayList的底层操作机制

(1)ArrayList中维护了一个的数组elementData,数组类型为Object。
transient Object[] elementData;
(2)当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍,依次都是1.5倍扩容。
(3)如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍。依次完后都是1.5倍扩容。

3. ArrayList的底层源码分析(无参构造器)

(1)示例代码:

package demo.arraylist_;

import java.util.ArrayList;

/**
 * @Package: demo.arraylist_
 * @ClassName: ArrayList_
 * @Author: 爱吃凉拌辣芒果
 * @CreateTime: 2021/10/19 14:46
 * @Description: ArrayList的底层操作机制
 * 使用无参构造器创建 ArrayList 对象
 */
public class ArrayList_ {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        //使用 for 给 list 集合添加 1-10 数据
        for (int i = 1; i <= 10; i++) {
            list.add(i);
        }
        //使用 for 给 list 集合添加 11-15 数据
        for (int i = 11; i <= 15; i++) {
            list.add(i);
        }
        list.add(100);
        list.add(200);
        list.add(null);
    }
}

(2)Debug过程分析
【1创建一个空的elementData数组】 在这里插入图片描述

其中设计到的几个参数分别为:
(1)size:ArrayList的大小,指包含元素的个数
在这里插入图片描述
(2)moCount:被修改的次数在这里插入图片描述
(3)elementData:存储ArrayList元素的数组缓冲器区在这里插入图片描述
(4)default_capacity:默认初始值为10在这里插入图片描述【2.数据装箱】
在这里插入图片描述
【3.确保内部容量】
在这里插入图片描述
【4.计算容量】
在这里插入图片描述
【5.第一次扩容为10】
在这里插入图片描述

【6.第一次真正的扩容】
在这里插入图片描述
【7.扩容算法】
在这里插入图片描述
【8.存入数据】
在这里插入图片描述
【9.第2次扩容】
在这里插入图片描述
【10.第2次扩容开始】
在这里插入图片描述
【11.第2次真正的扩容】
在这里插入图片描述
【12.第3次扩容】
在这里插入图片描述

【13.第3次扩容存入数据】
在这里插入图片描述

六、Vector类

1. 介绍

(1)Vector类的定义说明
public class vectorextends AbstractList
implements List,RandomAccess,cloneable,Serializable
(2)Vector底层也是一个对象数组
protected object[] elementData;
(3)Vector是线程同步的,即线程安全
Vector类的操作方法带有synchronized。
例如:
public synchronized E get(int index){ if (index >= elementCount) throw new ArraylndexOutOfBoundsExceptio (index);return elementData(index);
}
(4)在开发中,需要线程同步安全时,考虑使用Vector

2. Vector的底层操作机制

(1)当创建Vector对象时,如果使用的是无参构造器,则初始elementData容量为10,若满了之后扩容,容量为原来的2倍。
(2)如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为2倍。

七、ArrayList类与Vector类的比较

在这里插入图片描述

八、LinkedList类(链表类)

1. 介绍

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

2. LinkedList类的底层操作机制

(1)LinkedList底层维护了一个双向链表.
(2)LinkedList中维护了两个属性first和last分别指向首节点和尾节点,
(3)每个节点(Node对象),里面又维护了prev、next、 item三个属性,其中通过prev指向前一个,通过next指向后一个节点。最终实现双向链表.
(4)所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高。
在这里插入图片描述

3. LinkedList类的常用方法

LinkedList linkedList = new LinkedList();

(1)add 末尾添加一个节点元素

   linkedList.add(100);
   linkedList.add(200);
   linkedList.add(300);
   linkedList.add(400);

(2)remove() 默认删除的是第一个结点

linkedList.remove();

(3)remove(1) 删除索引为1的节点并返回item

【索引从0开始】
Object remove = linkedList.remove(1);

(4)remove(new Integer(300)) 删除数值为300的节点并返回确认

注意形参传入的为一个对象object
boolean b = linkedList.remove(new Integer(300));

(5)set(1, 999) 修改某个结点对象,将索引为1的对象的item修改为999

【索引从0开始】
linkedList.set(1, 999);

(6)get(1) 得到某个索引为1的结点对象

【索引从0开始】
Object o = linkedList.get(1);
System.out.println(o);

九、ArrayList类与LinkedList类的比较

如何选择ArrayList和LinkedList:
(1)如果我们改、查的操作多,选择ArrayList
(2)如果我们增、删的操作多,选择LinkedList
(3)一般来说,在程序中,80%-90%都是查询,因此大部分情况下会选择ArrayList
(4)在一个项目中,根据业务灵活选择,也可能这样,一个模块使用的是ArrayList,另外一个模块是LinkedList,也就是说,要根据业务来进行选择。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃凉拌辣芒果

不断学习,不断进步,共勉~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值