栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【Java集合】List接口、ArrayList、Vector、LinkedList

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Java集合】List接口、ArrayList、Vector、LinkedList

文章目录

一、List接口

常用方法List集合的三种遍历方式 二、ArrayList

源码详解——扩容机制 三、Vector

Vector和ArrayList的比较 四、linkedList

常用方法模拟简单链表源码详解

add方法remove方法 五、ArrayList和linkedList的比较

一、List接口

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

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

List接口特点:

元素存取有序。
例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的。

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

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

常用方法

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

void add(int index, E element):将指定的元素,添加到该集合中的指定位置上。
boolean addAll(int index, Collection c):将指定集合中的所有元素,添加到该集合中的指定位置上。

E get(int index):返回集合中指定位置的元素。

int indexOf(Object o):返回o在集合中首次出现的位置,没有则返回-1。
int lastIndexOf(Object o):返回o在集合中最后一次出现的位置,没有则返回-1。

E remove(int index):移除列表中指定位置的元素,返回的是被移除的元素。

E set(int index, E element):用指定元素替换集合中指定位置的元素,返回值的更新前的元素。相当于替换。

List subList(int fromIndex, int toIndex):返回从fromIndex位置到toIndex位置的子集合,前闭后开,不包含toIndex位置的元素。

List集合的三种遍历方式

第一种: 迭代器

Iterator iter = list.itertor();
while(iter.hasNext()) {
	Object o = iter.next();
}

第二种: 增强for

for(Object o : list) {
}

第三种: 普通for

for(int i = 0; i < list.size(); i++) {
	Object o = list.get(i);
}
二、ArrayList

java.util.ArrayList是大小可变的数组的实现,存储在内的数据称为元素。此类提供一些方法来操作内部存储的元素。 ArrayList中可不断添加元素,其大小也自动增长。

ArrayList可以加入null,并且可以多个。
ArrayList基本等同于Vector,但是ArrayList是线程不安全的(执行效率更高),所以在多线程的情况下,不建议使用ArrayList。

// 基本格式:
ArrayList list = new ArrayList();

// 在JDK 7后,右侧泛型的尖括号之内可以留空,但是<>仍然要写。简化格式:
ArrayList list = new ArrayList<>();

常用方法和List接口、Collection接口一样。

public class Demo01ArrayListMethod {
    public static void main(String[] args) {
        //创建集合对象
        ArrayList list = new ArrayList();
        //添加元素
        list.add("hello");
        list.add("world");
        list.add("java");
        //public E get(int index):返回指定索引处的元素
        System.out.println("get:"+list.get(0));
        System.out.println("get:"+list.get(1));
        System.out.println("get:"+list.get(2));
        //public int size():返回集合中的元素的个数
        System.out.println("size:"+list.size());
        //public E remove(int index):删除指定索引处的元素,返回被删除的元素
        System.out.println("remove:"+list.remove(0));
        //遍历输出
        for(int i = 0; i < list.size(); i++){
            System.out.println(list.get(i));
        }
    }
}
源码详解——扩容机制

ArrayList中维护了一个Object类型的数组elementData
transient关键字:表示瞬间、短暂的,改属性不会被序列化

当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第一次添加时,扩容为10,如需再次扩容,则扩容为elementData的1.5倍。
① 当new一个ArrayList对象的时候会进入空参构造,并初始化一个长度为0的空数组。
② 调用add方法时,会先确定是否需要扩容,然后再将元素存入集合中。



后面再次扩容时,就是按照1.5倍扩容。然后将原数组的数据,使用Arrays.copyOf()方法拷贝到新的数组中。

如果使用的是指定大小的构造器,则初始elementData容量为指定的大小,如需扩容,则直接扩容elementData的1.5倍。
① 当new一个ArrayList对象的时候会进入有参构造,并初始化一个长度为传入的大小的数组。
② 这里就和上面的一样了,调用add方法时,会先确定是否需要扩容,然后再将元素存入集合中。

三、Vector

Vector底层也是一个对象数组,protected Object[] elementData;。
Vector是线程同步的,即线程安全,Vector类的操作方法带有synchronized关键字。
所以,在开发中,需要线程同步安全时,使用Vector。

扩容机制与ArrayList类似,这里不做赘述。

Vector和ArrayList的比较
底层结构版本线程安全(同步)、效率扩容机制
ArrayList可变数组JDK 1.2不安全,效率高如果有参构造1.5倍
如果无参构造:
1. 第一次是10
2. 从第二次扩容开始,按1.5倍
Vector可变数组JDK 1.0安全,效率不高如果无参构造,默认10,第二次开始按2倍扩容
如果有参构造,每次按2倍扩容
四、linkedList

java.util.linkedList集合数据存储的结构是链表结构,方便元素添加、删除的集合,linkedList是一个双向链表。

可以添加任意元素,并且可以重复,包括null。

线程不安全,没有实现同步。

所以linkedList提供了大量首尾操作的方法。linkedList是List的子类,List中的方法linkedList都是可以使用,linkedList集合也可以作为堆栈、队列的结构使用。

常用方法

因为linkedList实现了List接口,所以List接口中的所有方法linkedList也可以使用,这里列出了linkedList常用的独有的方法。

void addFirst(E e):将指定元素插入此列表的开头
void addLast(E e):将指定元素添加到此列表的结尾

E getFirst():返回此列表的第一个元素
E getLast():返回此列表的最后一个元素

E removeFirst():移除并返回此列表的第一个元素
E removeLast():移除并返回此列表的最后一个元素

E pop():从此列表所表示的堆栈处弹出一个元素

void push(E e):将元素推入此列表所表示的堆栈

boolean isEmpty():如果列表不包含元素,则返回true

模拟简单链表

linkedList中维护了两个属性,first和last分别指向了首节点和尾结点,每个节点(Node对象),里面又维护了prev、next、item三个属性,其中通过prev指向前一个,通过next后一个,最终实现双向链表。

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

定义一个Node类:

//定义一个Node类,Node对象表示双向链表的一个节点
class Node {
    // 存放的数据
    public Object item;
    // 下一个节点
    public Node next;
    // 上一个节点
    public Node prev;

    public Node(Object item) {
        this.item = item;
    }
    
    @Override
    public String toString() {
        return "Node item = " + item;
    }
}

测试类:使用双向链表

public class linkedList01 {
    public static void main(String[] args) {
        // 模拟一个双向链表
        Node tom = new Node("tom");
        Node jack = new Node("jack");
        Node arbor = new Node("arbor");

        // 连接三个节点,形成双向链表
        // tom → jack → arbor
        tom.next = jack;
        jack.next = arbor;

        // arbor → jack → tom
        arbor.prev = jack;
        jack.prev = tom;

        // 定义一个头节点,指向tom
        Node first = tom;
        // 定义一个尾结点,指向arbor
        Node last = arbor;

        // 链表添加节点 在jack和arbor之间插入zhangsan节点
        // 因为没有数组,不用扩容和拷贝,所以增删更快
        Node zhangsan = new Node("zhangsan");
        zhangsan.prev = jack;
        zhangsan.next = arbor;
        jack.next = zhangsan;
        arbor.prev = zhangsan;

        // 链表删除节点 删除jack节点
        tom.next = zhangsan;
        zhangsan.prev = tom;

        // 使用双向链表,从头节点到尾节点遍历
        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.prev;
        }
    }
}
源码详解 add方法

当使用空参构造new一个linkedList时,空参构造是没有语句执行的。

此时,长度为0,第一个节点和最后一个节点都是null。

当程序走到linkedList.add(1);时,走的是下面这个方法:

进入linkLast方法,进行以下分析:

再次执行add方法,新增加一个节点,又会进入linkLast方法:

remove方法

调用空参的remove()方法,会删除链表的第一个节点。

进入removeFirst()方法可以看到,会先判断first节点是否为空(也就是判断是否为空链表),如果不是空的话,进行删除:
通过分析

五、ArrayList和linkedList的比较
底层结构增删的效率改查的效率
ArrayList可变数组较低,扩容数组较高
linkedList双向链表较高,链表追加较低

如果改查多,选择ArrayList
如果增删多,选择linkedList

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/762689.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号