List接口包含List接口及List接口的所有实现类,List集合中的元素允许重复。

List接口

List接口继承了Collection接口,包含Collection接口的所有方法,还定义了两个非常重要的方法

get(int index): 获得指定索引位置的元素

set(int index, Object obj):将集合中指定索引位置的对象修改为指定对象

List接口的实现类

List接口的实现类有ArrayList和LinkedList

  • ArrayList实现了可变的数组(底层是数组实现),允许保存所有元素,可以根据索引位置进行快速的随机访问;缺点是向指定索引位置插入对象或删除对象的速度较慢
  • LinkedList采用链表结构保存对象(底层是链表实现),优点是便于向集合中插入和删除对象

实例化集合

List<E> list = new ArrayList<>();

List<E> list2 = new LinkedList<>();

E是合法的java类型

ArrayList

ArrayList是Java集合框架中使用最多的一个类,是一个数组队列,线程不安全集合。

它继承于AbstractList,实现了List, RandomAccess, Cloneable, Serializable接口。

  1. ArrayList实现List,得到了List集合框架基础功能;
  2. ArrayList实现RandomAccess,获得了快速随机访问存储元素的功能,RandomAccess是一个标记接口,没有任何方法;
  3. ArrayList实现Cloneable,得到了clone()方法,可以实现克隆功能;
  4. ArrayList实现Serializable,表示可以被序列化,通过序列化去传输,典型的应用就是hessian协议。

它具有如下特点:

  • 容量不固定,随着容量的增加而动态扩容(阈值基本不会达到)
  • 有序集合(插入的顺序==输出的顺序)
  • 插入的元素可以为null
  • 增删改查效率更高(相对于LinkedList来说)
  • 线程不安全

ArrayList底层实现

ArrayList底层是使用数组来实现的

源码解析:

// 重要的几个变量

private static final int DEFAULT_CAPACITY = 10;

// 用数组保存arraylist的对象

transient Object[] elementData;

private int size;

//ArrayList初始化,实际是初始化一个存放object的数组

public ArrayList() {

     this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

}

// grow方法,扩充ArrayList,通过Arrays.copyOf()方法返回一个扩充完毕的新数组,往ArrayList最后面添加一个元素

    private void grow(int minCapacity) {

        // overflow-conscious code

        int oldCapacity = elementData.length;

        int newCapacity = oldCapacity + (oldCapacity >> 1);

        if (newCapacity - minCapacity < 0)

            newCapacity = minCapacity;

        if (newCapacity - MAX_ARRAY_SIZE > 0)

            newCapacity = hugeCapacity(minCapacity);

        // minCapacity is usually close to size, so this is a win:

        elementData = Arrays.copyOf(elementData, newCapacity);

    }

// 指定index添加元素,通过System.arraycopy给数组添加值   

    public void add(int index, E element) {

        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!

        System.arraycopy(elementData, index, elementData, index + 1,size - index);

        elementData[index] = element;

        size++;

    }

  

Arrays.copyOf和System.arraycopy

  1. System.arraycopy()需要目标数组,将原数组拷贝到你自己定义的数组里,而且可以选择拷贝的起点和长度以及放入新数组中的位置
  2. Arrays.copyOf()是系统自动在内部新建一个数组,调用System.arraycopy()将original内容复制到copy中去,并且长度为newLength。返回copy; 即将原数组拷贝到一个长度为newLength的新数组中,并返回该数组。

Array.copyOf()可以看作是受限的System.arraycopy(),它主要是用来将原数组全部拷贝到一个新长度的数组,适用于数组扩容。

LinkedList

LinkedList是一个双向链表,每一个节点都拥有指向前后节点的引用。相比于ArrayList来说,LinkedList的随机访问效率更低。

它继承AbstractSequentialList,实现了List, Deque, Cloneable, Serializable接口。

  1. LinkedList实现List,得到了List集合框架基础功能;
  2. LinkedList实现Deque,Deque 是一个双向队列,也就是既可以先入先出,又可以先入后出,说简单些就是既可以在头部添加元素,也可以在尾部添加元素;
  3. LinkedList实现Cloneable,得到了clone()方法,可以实现克隆功能;
  4. LinkedList实现Serializable,表示可以被序列化,通过序列化去传输,典型的应用就是hessian协议。

LinkedList的底层实现

LinkedList的底层实现是双向链表,因此它有个内部类Node代表每个节点,即存储的每个元素

 private static class Node<E> {

        E item;

        Node<E> next;

        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next) {

            this.item = element;

            this.next = next;

            this.prev = prev;

        }

    }

  

我们来看LinkedList是如何进行删除和添加元素的:

// 增加LinkedList头元素

    private void linkFirst(E e) {

        final Node<E> f = first;

        final Node<E> newNode = new Node<>(null, e, f);

        first = newNode;

        if (f == null)

            last = newNode;

        else

            f.prev = newNode;

        size++;

        modCount++;

    }

    // 增加LinkedList尾元素

    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++;

    }

    // 在index处增加元素

    public void add(int index, E element) {

        checkPositionIndex(index);

        if (index == size)

            linkLast(element);

        else

            linkBefore(element, node(index));

    }

    // node(index)是获取index处的元素

    // linkBefore是在元素前增加一个元素

    // 删除index处的元素

    // 先检查元素是否存在,然后解链

    public E remove(int index) {

        checkElementIndex(index);

        return unlink(node(index));

    }

  

总结,以上就是List两个重要的实现类ArrayList和LinkedList的实现和常用的方法的源码介绍,后续我们根据实际需要处理来选择不同的实现类来帮助我们处理问题。

java集合类-List接口的更多相关文章

  1. Java集合类根接口:Collection 和 Map

    前言 在前文中我们了解了几种常见的数据结构,这些数据结构有着各自的应用场景,并且被广泛的应用于编程语言中,其中,Java中的集合类就是基于这些数据结构为基础. Java的集合类是一些非常实用的工具类, ...

  2. java集合类-Set接口

    Set集合 Set集合中的对象不按特定的方式排序,只是简单的把对象放入集合中,但是不能包含重复对象. Set集合由Set接口和Set接口的实现类组成,Set接口继承与于Collection接口 Set ...

  3. Java集合类源码解析:AbstractMap

    目录 引言 源码解析 抽象函数entrySet() 两个集合视图 操作方法 两个子类 参考: 引言 今天学习一个Java集合的一个抽象类 AbstractMap ,AbstractMap 是Map接口 ...

  4. Java集合类框架的基本接口有哪些?

    总共有两大接口:Collection 和Map ,一个元素集合,一个是键值对集合: 其中List和Set接口继承了Collection接口,一个是有序元素集合,一个是无序元素集合: 而ArrayLis ...

  5. Java集合类——Set、List、Map、Queue接口

    目录 Java 集合类的基本概念 Java 集合类的层次关系 Java 集合类的应用场景 一. Java集合类的基本概念 在编程中,常需要集中存放多个数据,数组是一个很好的选择,但数组的长度需提前指定 ...

  6. 牛客网Java刷题知识点之Java集合类里面最基本的接口有哪些

    不多说,直接上干货! https://www.nowcoder.com/ta/review-java/review?tpId=31&tqId=21086&query=&asc= ...

  7. java集合类框架的基本接口有哪些

    集合类接口指定了一组叫做元素的对象.集合类接口的每一种具体的实现类都可以以他自己的方式对元素进行保存和排序.有的集合允许重复的键,有些不允许. java集合类里面最基本 的接口: Collection ...

  8. Java集合类--温习笔记

    最近面试发现自己的知识框架有好多问题.明明脑子里知道这个知识点,流程原理也都明白,可就是说不好,不知道是自己表达技能没点,还是确实是自己基础有问题.不管了,再巩固下基础知识总是没错的,反正最近空闲时间 ...

  9. 做JavaWeb开发不知Java集合类不如归家种地

    Java作为面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,就要对对象进行存储.但是使用数组存储对象方面具有一些弊端,而Java 集合就像一种容器,可以动态地把多个对象的引用放入容 ...

随机推荐

  1. Django 中 app_name (应用命名空间) 和 namespace (实例命名空间) 的区别

    转自:https://www.jianshu.com/p/404500a0408a 补充理解: 先把官网上对应用命名空间(app_name)和实例命名空间(namespace)的解释贴上: app_n ...

  2. (一)第一个python语句、乘除法、获取用户输入、函数

    一.print语句 >>> print "hello World!!" python2 和python3 的print是不一样的,python3的print(“h ...

  3. VBA Excel宏(二)

    在本章中,我们来学习如何逐步编写一个简单的宏. 第1步 - 首先,在Excel 2016中启用“开发者”菜单.要完成这个设置,请点击左上角菜单:文件 -> 选项.如下图所示 - 第2步 - 点击 ...

  4. $.serializeArray()获取不到input的value值bug问题

    今天修改form表单,发现有好几个input值保存不上,上网搜索了一下是$.serializeArray()获取不到disabled的值.如果想要让input元素变为不可用,可以把input设为rea ...

  5. List · leetcode-24. 交换相邻节点

    题面 Given a linked list, swap every two adjacent nodes and return its head. You may not modify the va ...

  6. OpenCV实现图象翻转、滤波、锐化

    OpenCV实现图象翻转.滤波.锐化 注:以下代码,使用opencv库函数实现了对图片的翻转.灰度图转换.各种滤波.各种锐化. 库函数相关参数及说明参阅:OpenCV中文站=>opencv教程( ...

  7. ubuntu创建kvm虚拟机

    CPU虚拟化支持 [root@ubuntu~]# egrep -o '(vmx|svm)' /proc/cpuinfo vmx vmx vmx vmx KVM环境 [root@ubuntu ~]# a ...

  8. Mybatis设计模式

    mybatis中使用到的设计模式 Mybatis 使用的 9 种设计模式 建造者模式(Configuration) 构造者模式的定义是“将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不 ...

  9. 深度学习_1_Tensorflow_2_数据_文件读取

    tensorflow 数据读取 队列和线程 文件读取, 图片处理 问题:大文件读取,读取速度, 在tensorflow中真正的多线程 子线程读取数据 向队列放数据(如每次100个),主线程学习,不用全 ...

  10. python获取字符串的前几个字符(包含汉字)

    一个简单的字符串,比如a="小明xiaoming"或者b="小xiao明ming".想在只想得到字符串的前4个元素,a1="小明xi",b= ...