JavaSE:List以及ArrayList 和 LinkedList

JavaSE:List以及ArrayList 和 LinkedList,第1张

目录

List接口特有的常用方法

ArrayList

集合ArrayList 的构造方法

将 ArrayList 转换为线程安全的方法

LinkedList

LinkedList构造方法

ArrayList 和 Array 的区别

ArrayList 和 LinkedList 的区别

Vector


List接口特有的常用方法

List存储元素特点:有序可重复,且List集合中元素有下标(从0开始)

(1)void add(int index,E element) 在列表的指定位置插入指定元素

index索引即是该List中的下标,element为你插入的元素,如下图:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class List方法 {
    public static void main(String[] args) {
        List arr = new ArrayList();
        arr.add("a");
        arr.add("b");
        arr.add("c");
        //调用List中特有的add方法
        arr.add(2,"java");
        Iterator it = arr.iterator();
        while (it.hasNext()){
            Object ob = it.next();
            System.out.println(ob);
        }
    }
}

结果图:

(2)E set(int index,E element) 用指定元素替换列表中指定位置的元素

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

public class List方法 {
    public static void main(String[] args) {
        List arr = new ArrayList();
        arr.add("a");
        arr.add("b");
        arr.add("c");
        arr.add("a");
        System.out.println("初始的元素序列为:");
        for( int i = 0 ; i < arr.size() ; i++){
            Object obj = arr.get(i);
            System.out.println(obj);
        }
        //替换指定位置下标的元素
        arr.set(2,"java");
        System.out.println("替换后后元素序列为:");
        for( int i = 0 ; i < arr.size() ; i++){
            Object obj = arr.get(i);
            System.out.println(obj);
        }
    }
}

结果图:

 (3)E get(int index) 返回列表中指定位置的元素

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

public class List方法 {
    public static void main(String[] args) {
        List arr = new ArrayList();
        arr.add("a");
        arr.add("b");
        arr.add("c");
        //调用List中特有的add方法
        arr.add(2,"java");
        for( int i =0 ; i< arr.size(); i++){
            //调用get方法
            Object obj = arr.get(i);
            System.out.println(obj);
        }
    }
}

结果图:

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

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

public class List方法 {
    public static void main(String[] args) {
        List arr = new ArrayList();
        arr.add("a");
        arr.add("b");
        arr.add("c");
        arr.add("a");
        //获取 “a” 第一次出现时的索引
        System.out.println(arr.indexOf("a"));
        //获取 “a” 最后一次出现时的索引
        System.out.println(arr.lastIndexOf("a"));
        //如果没有指定元素时
        System.out.println(arr.indexOf("java"));
    }
}

结果图:

(5)E remove(int index) 移除列表中指定位置的元素

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

public class List方法 {
    public static void main(String[] args) {
        List arr = new ArrayList();
        arr.add("a");
        arr.add("b");
        arr.add("c");
        arr.add("a");
        System.out.println("初始的元素序列为:");
        for( int i = 0 ; i < arr.size() ; i++){
            Object obj = arr.get(i);
            System.out.println(obj);
        }
        //删除指定位置下标的元素
        arr.remove(3);
        System.out.println("删除后元素序列为:");
        for( int i = 0 ; i < arr.size() ; i++){
            Object obj = arr.get(i);
            System.out.println(obj);
        }
    }
}

结果图:

ArrayList

(1)ArrayList 初始化容量为0,可以指定容量,未添加元素时为一个空数组,添加元素后默认容量由0 变为10

    /**
     * Default initial capacity.
     */
    private static final int DEFAULT_CAPACITY = 10;

(2)集合底层是一个Object类型的数组

    /**
     * Shared empty array instance used for empty instances.
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

(3)会自动扩容1.5倍

先将旧容量右移1位,再加上旧容量就得到了新容量,正数右移1位相当于除以2,在该基础上加旧容量,则等价于新容量 = 旧容量 * 1.5,所以才有ArrayList每次扩容为旧容量的1.5倍的说法,最后调用Arrays.copyOf()方法进行拷贝,并将elementData指向新数组,而旧数组因为没有引用指向它,很快就会被垃圾收集器回收掉

    /**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     *
     * @param minCapacity the desired minimum capacity
     * @throws OutOfMemoryError if minCapacity is less than zero
     */
    private Object[] grow(int minCapacity) {
        int oldCapacity = elementData.length;
        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth */
                    oldCapacity >> 1           /* preferred growth */);
            return elementData = Arrays.copyOf(elementData, newCapacity);
        } else {
            return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
        }
    }
集合ArrayList 的构造方法
ArrayList()构造一个初始容量为十的空列表
ArrayList(int initialCapacity)构造具有指定初始容量的空列表
ArrayList(Collection c)构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序

(1)无参构造

/**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * will be expanded to DEFAULT_CAPACITY when the first element is added.
     * ArrayList的缓冲数组,里面存储的是ArrayList数据。ArrayList的容量长度就是这个数组的长度,任何空的使用elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA初始化的ArrayList在添加第一个元素时都会被扩容为DEFAULT_CAPACITY (10)
     */
    transient Object[] elementData;    
 /**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     * 用于默认大小的空的共享空数组实例。我们将此与EMPTY_ELEMENTDATA区分开来,以便在添加第一个元素时知道需要扩张多少。
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
 /**
     * Constructs an empty list with an initial capacity of ten.
     * 构造一个初始容量为10的空list。
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

(2)指定容量ArrayList(int initialCapacity)

        入参是ArrayList初始化容量,如果容量小于0就抛错,否则实例化一个Object对象数组赋值给全局变量elementData

public ArrayList(int initialCapacity) {
    // 容量大于0,按照指定的容量初始化数组
    if (initialCapacity > 0) {
        // 创建一个数组,且指定长度为initialCapacity
        this.elementData = new Object[initialCapacity];
    // 如果initialCapacity容量为0,把EMPTY_ELEMENTDATA的地址赋值给elementData
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    // 容量小于0,抛非法异常    
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
    }
}

(3)指定集合ArrayList(Collection c)

        传入Collection集合的对象,将传入的集合对象转为数组,然后给size赋值,判断如果传入的对象数组不是Object[],则转为Object[]

public ArrayList(Collection c) {
    // 将给定的集合对象转成数组,且将数组的地址赋值给elementData
    elementData = c.toArray();
    // 将elementData的长度赋值给集合长度size,且判断是否不等于 0
    if ((size = elementData.length) != 0) {
        // 判断elementData 和 Object[] 是否为不一样的类型
        // c.toArray()数组不是object数组进行转换成Object[]
        // 每个集合的toarray()的实现方法不一样,所以需要判断一下,如果不是Object[].class类型,那么就需要使用ArrayList中的方法去改造一下。
        // elementData.getClass()到底是什么类型的?
        if (elementData.getClass() != Object[].class)
            // 转换Object[] 
            // 如果不一样,使用Arrays的copyOf方法进行元素的拷贝
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // 给定的数组的长度为0,用空数组代替
        this.elementData = EMPTY_ELEMENTDATA;
    }
}
将 ArrayList 转换为线程安全的方法

Collections.synchronizedList()

import java.util.Collections;
import java.util.List;
import java.util.ArrayList;


public class ArrayListTest {
    public static void main(String[] args) {
        //默认容量为10,此时线程是不安全的
        List list1 = new ArrayList();
        //变成线程安全的方法
        Collections.synchronizedList(list1);
        
        list1.add(1);
        list1.add(1);
        list1.add(1);
        list1.add(1);
    }
}
LinkedList

(1)LinkedList 的底层是一个双向链表(包含两个指针的,pre指向前一个节点,next指向后一个节点,但是第一个节点head的pre指向null,最后一个节点的tail指向null)

注意:JDK1.6时为双向循环链表(第一个节点的pre指向最后一个节点,最后一个节点的next指向第一个节点,也形成一个“环”)而在JDK1.7以及往后版本,底层实现为双向链表

JDK1.8源码

public class LinkedList
    extends AbstractSequentialList
    implements List, Deque, Cloneable, java.io.Serializable
{
    //长度
    transient int size = 0;
    //指向头结点
    transient Node first;
    //指向尾结点
    transient Node last;
}

(2)元素在空间存储上的内存不连续,随机增删元素时,不会有大量元素移动,所以增删效率高,查找效率低

LinkedList构造方法

(1)无参构造(public LinkedList())

    /**
     * Constructs an empty list.
     */
    public LinkedList() {
    }

(2)有参构造(public LinkedList(Collection c))

    /**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param  c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
    public LinkedList(Collection c) {
        this();
        addAll(c);
    }
ArrayList 和 Array 的区别
Array 可以容纳基本类型和对象,而 ArrayList 只能容纳对象。 Array 是指定大小的,而 ArrayList 大小是固定
ArrayList 和 LinkedList 的区别
(1)ArrrayList 底层的数据结构是数组,支持随机访问,而 LinkedList 的底层数据结构是双向循环链表,不支持随机访问 (2)使用下标访问一个元素, ArrayList 的时间复杂 度是 O(1) ,而 LinkedList O(n)
Vector

(1)Vector 底层也是一个数组,初始化容量为10

(2)扩容后,容量为原容量的两倍

(3)Vector 中的所有方法都是线程同步的,线程是安全的

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/790420.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-05
下一篇 2022-05-05

发表评论

登录后才能评论

评论列表(0条)

保存