Java集合之List(一)

Java集合(一)List(ArrayList,LinkedList,Vetor)

本节讲解Collection接口的子接口 ---------List接口
List接口 也称为有序集合(序列)单列集合,缺点是可能拥有重复元素
List主要应用是它的三个实现类ArrayList,LinkedList,Vector

1.ArrayList 数组列表

底层原理是创建新的数组,数组你可以看成线性表结构存储数据
特点:非线程安全,查询快,添加和删除缓慢

而线性表的特点就是查询非常方便快捷,但是在中间添加(或删除)元素,就需要该元素后面的所有元素往前(或往后)挪动位置。这显得效率非常低下,远不如链表添加和删除元素效率高,后面讲链表为什么添加和删除效率高,而查询又特别慢了。

构造方法
构造器描述
ArrayList()构造一个初始容量为10的空列表。
ArrayList​(int initialCapacity)构造具有指定初始容量的空列表。
ArrayList​(Collection<? extends E> c)按照集合的迭代器返回的顺序构造一个包含指定集合元素的列表。

容量

int size()方法 返回此列表中的元素数。 如果此列表包含超过Integer.MAX_VALUE元素,则返回Integer.MAX_VALUE

add()方法(面试题会问add方法返回什么?
这是Java源码

public boolean add(E e) {
    modCount++;
    add(e, elementData, size);
    return true;//注意一直返回true,哪怕内存不够失败了也返回true
}

初始化创建的时候,你可以给容量赋值具体大小,如果不赋值就默认为0,源码上面写的是默认为10,事实上当不添加时,容量为0(可以通过反射来了解),第一次使用add()方法时,添加第一个元素时,ArrayList初始化新数组容量为10,当超出容量时,发现其自动扩容公式为capacity=capacity+(capacity>>1)(二进制向右移1位,即除以2),即容量x1.5,这也会造成一个问题就是每次内存不够用,就自动扩容1.5倍,而他的底层原理是使用Array.copyOf()方法创建新的数组,因此会很浪费内存空间。

ArrayList<Integer> arrayList = new ArrayList<>(容量);//创建

查看源码,同时会发现ArrayList的最大数组大小是Integer.MAX_VALUE - 8???

/**
     * The maximum size of array to allocate (unless necessary).
     * Some VMs reserve some header words in an array.
     * Attempts to allocate larger arrays may result in
     * OutOfMemoryError: Requested array size exceeds VM limit
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
数组对象的形状和结构(如int值数组)与标准Java对象类似。主要区别在于数组对象有一个额外的元数据,
用于表示数组的大小。然后,数组对象的元数据由以下部分组成:Class:指向描述对象类型的类信息的指针。
在int数组的情况下,这是一个指向int []类的指针。

你可能和我一样有疑问了,ArrayList()既然原理是数组,那它的实际length是多少,size()方法会返回它的实际存储元素数量,但是ArrayList()没有length()方法,所以只能够通过反射查看ArrayList的实际大小
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;

public class ArrayListDemo {
    public static void main(String args[]) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        System.out.println(getArrayListCapacity(arrayList));
        arrayList.size();

        //增加元素,使其扩容
        arrayList.add(0);
        System.out.println(getArrayListCapacity(arrayList));

        for(int i = 0; i < 10; ++i)
            arrayList.add(0);
        System.out.println(getArrayListCapacity(arrayList));

        for(int i = 0; i < 5; ++i)
            arrayList.add(0);
        System.out.println(getArrayListCapacity(arrayList));
    }

    public static int getArrayListCapacity(ArrayList<?> arrayList) {
        Class<ArrayList> arrayListClass = ArrayList.class;
        try {
            Field field = arrayListClass.getDeclaredField("elementData");
            field.setAccessible(true);
            Object[] objects = (Object[])field.get(arrayList);
            return objects.length;
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
            return -1;
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            return -1;
        }
    }
}

2.Vetor

特点:拥有synchronized关键字,线程同步,线程安全

构造方法
构造器描述
Vector()构造一个初始容量为10的空列表,其标准容量增量为零
Vector​(int initialCapacity)构造一个具有指定初始容量且容量增量等于零的空向量
Vector​(Collection<? extends E> c)按照集合的迭代器返回的顺序构造一个包含指定集合元素的列表
Vector​(int initialCapacity, int capacityIncrement)构造具有指定初始容量和容量增量的空向量

可以通过对比ArrayList,会发现多一个构造方法 Vector​(int initialCapacity, int capacityIncrement),前一个参数定义它的初始容量,后一个参数人为定义它每次超出容量大小,就增加多少容量,当自定义的capacityIncrement<=0的时候,就自定义 容量x2

3.LinkedList

特点:基于双链表存储数据,双链表的特征是每次查询都需要从头或者从尾部依次查询,这就导致它的查询效率特别低,然而链表添加和删除只要改变它的前一个元素的后驱节点和后一个元素的前驱结点,因此非常的方便快捷,和ArrayList优缺点恰恰相反

因为查询效率低下,因此实际应用不是非常广泛

双链表可以从头部开始,也可以从尾部开始,因此可以用它来模仿栈,堆,队列就行数据操作

//堆
addFirst()
removeFirst()
//从头部添加,从头部删除,符合堆的特点:后进先出

//队列
addFirst()
removeLast()
//从头部添加,尾部删除,符合队列的特点:先进先出


//栈
push()//压栈
pop()//弹栈
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值