Java 中的 List (ArrayList 、LinkedList 、Vector)

List

List接口常用方法

List集合存储元素特点:有序可重复

List既然是Collection接口的子接口,那么肯定List接口有自己的“特色”方法

以下列出List特有的常用的方法:

  • void add(int index, E element) 将指定的元素插入此列表中的指定位置(可选操作)。

  • Object get(int index)返回此列表中指定位置的元素。

  • int indexOf(Object o) 返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。

  • int lastIndexOf(Object o) 返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。

  • Object remove(int index) 删除该列表中指定位置的元素(可选操作)。

  • Object set(int index, E element) 用指定的元素(可选操作)替换此列表中指定位置的元素。

import java.util.*;
/*
* 测试List接口中常用的方法、
* LIst集合存储元素特点:有序可重复
void add(int index, E element)  将指定的元素插入此列表中的指定位置(可选操作)。
Object  get(int index)返回此列表中指定位置的元素。
int   indexOf(Object o)   返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。
int   lastIndexOf(Object o)  返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。
Object  remove(int index) 删除该列表中指定位置的元素(可选操作)。
Object  set(int index, E element)  用指定的元素(可选操作)替换此列表中指定位置的元素。
* */
public class ListTest01 {
    public static void main(String[] args) {
        //创建List类型的集合
//        List myList = new LinkedList();
//        List myList = new Vector();
        List myList = new ArrayList();

        myList.add("A");
        myList.add("B");
        myList.add("C");
        myList.add("D");
        
        // 在列表指定位置插入元素
        // 这个方法使用的不多,对于ArrayList来说效率比较低
        myList.add(1,"king");

        Iterator it = myList.iterator();
        while(it.hasNext()){
            Object elt = it.next();
            System.out.println(elt);
        }

        //根据下表获取元素
        Object firstObj = myList.get(0);
        System.out.println(firstObj);

        // 通过下标遍历  [List集合特有的方式,Set没有]
        for (int i = 0; i < myList.size(); i++) {
            Object obj = myList.get(i);
            System.out.println(obj);

        }
    }
}

ArrayList

  • ArrayList集合初始化容量是10
  • ArrayList集合底层是Object类型的数组 Object []
  • ArrayList集合的扩容:原容量的1.5倍
  • ArrayList底层是数组,怎么优化?
    尽可能少的扩容,因为数组扩容的效率比较低,建议在使用ArrayList集合的时候,预估元素的个数,给定一个初始化容量
  • 数组的优点:检索效率比较高(每个元素占用空间大小相同,内存地址是连续的 ,知道首元素的内存地址,知道下标,我们就可以计算元素的内存地址,所以检索效率最高)
  • 数组的缺点:随机增删效率比较低,很难存储大数据量(很难找到一块非常巨大的连续的内存空间)
  • 向数组末尾添加元素效率还是比较高的
  • 面试官经常问的一个问题: 这么多集合中,你使用的哪个数组最多?
    ArrayList集合,因为往数组末尾添加元素,效率不受影响,另外我们检索/查找某个元素的操作比较多
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
/*
*ArrayList集合的扩容:原容量的1.5倍
* ArrayList底层是数组,怎么优化?
* 尽可能少的扩容,因为数组扩容的效率比较低,建议在使用ArrayList集合的时候,预估元素的个数,给定一个初始化容量
* 数组的优点:检索效率比较高(每个元素占用空间大小相同,内存地址是连续的 ,知道首元素的内存地址,知道下标,我们就可以计算元素的内存地址,所以检索效率最高)
* 数组的缺点:随机增删效率比较低,很难存储大数据量(很难找到一块非常巨大的连续的内存空间)
* 向数组末尾添加元素效率还是比较高的
* 面试官经常问的一个问题:  这么多集合中,你使用的哪个数组最多?
* ArrayList集合,因为往数组末尾添加元素,效率不受影响,另外我们检索/查找某个元素的操作比较多
* */
public class ArrayListTest01 {
    public static void main(String[] args) {
        //默认初始化容量是10 (底层先创建了一个长度为0的数组,当添加第一个元素的时候,初始化容量是10)
        //数组的长度是10
        List list1 = new ArrayList();
        //集合的size()方法是获得当前集合中元素的个数,不是获取集合的容量。
        System.out.println(list1.size()); //0
        List list2 = new ArrayList(20);
        System.out.println(list2.size()); //0

        list1.add(1);
        list1.add(1);
        list1.add(1);
        list1.add(1);
        list1.add(1);
        list1.add(1);
        list1.add(1);
        list1.add(1);
        list1.add(1);
        list1.add(1);
        System.out.println(list1.size());
        //再加一个元素
        list1.add(10);
        //新的容量增长1.5倍
        System.out.println(list1);

        //创建一个HashSet集合
        Collection c = new HashSet();
        c.add(100);
        c.add(50);
        c.add(66);
        c.add(610);
        c.add(100);

        //通过这个构造方法就可以将HashSet集合转化为ArrayList集合。
        List myList3 = new ArrayList(c);
        for (int i = 0; i < myList3.size(); i++) {
            System.out.println(myList3.get(i));
        }
    }
}

LinkedList链表

  • 单链表中的节点
  • 节点是单向链表的基本单元

链表优点:随机增删效率比较高(不需要大量数据进行位移)

链表缺点:查询效率比较低

import java.util.LinkedList;
import java.util.List;

/*
* 单链表中的节点
* 节点是单向链表的基本单元
* 链表的元素在空间存储上内存地址不连续
* 链表优点:随机增删效率比较高(不需要大量数据进行位移)
* 链表缺点:查询效率比较低
* */
public class LinkedListTest {
    public static void main(String[] args) {
        // LinkedList集合底层也有下标的
        // 注意:ArrayList之所以检索效率比较高,是因为底层数组发挥的作用、
        // LinkedList集合也有下标,但是检索/查找某个元素的时候效率比较低,因为只能从头节点开始一个个遍历
        List list = new LinkedList();
        list.add("a");
        list.add("b");
        list.add("c");

        for (int i = 0; i < list.size(); i++) {
            Object obj = list.get(i);
            System.out.println(obj);
        }
    }
}

  • LinkedList集合是双向的链表

  • 链表的元素在空间存储上内存地址不连续

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class LinkedListTest02 {
    public static void main(String[] args) {

        //LinkedList集合中有初始化容量吗?  没有。
        //最初这个链表中没有任何元素。first和Last 引用都是null
        // 不管是LinkedList还是ArrayList,以后写代码不需要关心具体是哪个集合
        // 因为我们要面向接口编程,调用的方法都是接口中的方法。
//        List list2 = new ArrayList(); // 这样写表示底层使用的数组
        List list2 = new LinkedList(); // 这样写表示底层使用的双向链表

        // 以下的方法都是面向的接口编程
        list2.add("abc");
        list2.add("456");
        list2.add("789");
        for (int i = 0; i < list2.size(); i++) {
            System.out.println(list2.get(i));
        }

    }
}

Vector

Vector:

  • 底层是一个数组

  • 初始化容量是10

  • 怎么扩容的?
    扩容之后是原容量的二倍。

  • ArrayList扩容后是之前的1.5倍

  • Vector中所有的方法都是线程同步的,都带有synchronized 关键字 ,
    是线程安全的,效率比较低,使用较少

  • 怎么将一个线程不安全的ArrayList集合转换成线程安全的?
    使用集合工具类: java.util.Collections;

    • java.util.Collections;是集合工具类
    • java.util.Collection; 是集合接口
import java.util.*;

/*
* Vector:
* 底层是一个数组
* 初始化容量是10
* 怎么扩容的?
* 扩容之后是原容量的二倍。
* ArrayList扩容后是之前的1.5倍
* Vector中所有的方法都是线程同步的,都带有synchronized 关键字 ,
* 是线程安全的,效率比较低,使用较少
* 怎么将一个线程不安全的ArrayList集合转换成线程安全的?
  使用集合工具类:
  * java.util.Collections;
  *
  * java.util.Collections;是集合工具类
  * java.util.Collection; 是集合接口 */
public class VectorTest {
    public static void main(String[] args) {

        Vector vec = new Vector();
        vec.add(1);
        vec.add(1);
        vec.add(1);
        vec.add(1);
        vec.add(1);
        vec.add(1);
        vec.add(1);
        vec.add(1);
        vec.add(1);
        vec.add(1);
        // 满了容量之后进行扩容,扩容直接扩成两倍
        vec.add(11);

        Iterator it = vec.iterator();
        while(it.hasNext()){
            Object obj = it.next();
            System.out.println(obj);
        }

        for (int i = 0; i < vec.size(); i++) {
            System.out.println(vec.get(i));
        }

        // 这个可能以后要使用!!!
        List myList = new ArrayList(); //非线程安全的

        // 变成线程安全的
        Collections.synchronizedList(myList);//这里没有办法看效果,还没学多线程,先记住!

        // myList集合现在是线程安全的了
        myList.add("111");
        myList.add("222");
        myList.add("333");

    }
}

posted @   十几里路  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤
点击右上角即可分享
微信分享提示