【Java】List接口,以及ArrayList,LinkedList,Vector的区别(源码解析)

1. List接口常用方法:

注:index与数组相同,从0开始

  • 根据下标返回元素:
    E get(int index);
  • 根据下标修改元素,返回修改前的元素
    E set(int index,E element);
  • 根据下标删除元素
    E remove(int index);
    E remove(new Integer(int value));
import java.util.ArrayList;
import java.util.List;

public class ListTest {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);//添加元素
        list.add(3);
        list.add(5);
        list.add(7);
        list.add(1);
        System.out.println(list);//输出数组
        System.out.println(list.size());//返回数组大小
        System.out.println(list.contains(7));//判断是否有这个元素
        System.out.println(list.get(3));//返回数组下标为3的数
        System.out.println(list.set(3,9));//将数组下标为3的数修改为9
        System.out.println(list.get(3));//再次返回数组下标为3的数,看是否修改成功
        System.out.println(list.remove(4));//删除的是索引位置的数
        System.out.println(list.remove(new Integer(5)));//删除数字5
        System.out.println(list);//打印数组
    }
}

结果:在这里插入图片描述

2. LIst集合中添加自定义类:

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

class Person{
    private String name;
    private Integer age;
    
    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class ListTest {
    public static void main(String[] args) {
        List<Person> people = new LinkedList<>();
        Person per1 = new Person("ll",20);
        Person per2 = new Person("hh",30);
        Person per3 = new Person("fwb",1);
        people.add(per1);
        people.add(per2);
        people.add(per3);
        System.out.println(people.contains(new Person("ll",20)));
        System.out.println(people.remove(new Person("zs",20)));
    }
}

这样添加的结果是输出了两个false,因为他需要覆写equals方法以获得比较元素的支持:

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

class Person{
    private String name;
    private Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    /*
    这是原方法中所调用的equals方法,只是比较地址是否相同
    public boolean equals(Object obj) {
        return (this == obj);
    }
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        //instanceof用来判断是否是这类的对象  
        if (!(obj instanceof Person))
            return false;
        //向下转型取出属性值比较
        Person per = (Person)obj;
        return this.age.equals(per.age) && this.name.equals(per.name);
    }
}
public class ListTest {
    public static void main(String[] args) {
        List<Person> people = new LinkedList<>();
        Person per1 = new Person("aaa",20);
        Person per2 = new Person("bbb",30);
        Person per3 = new Person("ccc",1);
        people.add(per1);
        people.add(per2);
        people.add(per3);
        //Object obj = new Person("aaa",20);
        //父类 父类引用 = new 子类();这是向上转型
        System.out.println(people.contains(new Person("aaa",20)));
        System.out.println(people.remove(new Person("张三",20)));
    }
}

此时的输出结果是true与false是我们想要的结果。


3. List接口中ArrayList,LinkedList,Vector的区别

1. ArrayList: JKD1.2
  1. 数组实现
    1.1 初始化策略:Lazy-Load(懒加载策略):只有当对象第一次被使用(add)时,内部的数组才会初始化为长度为10的数组。
    1.2 扩容策略:每次扩容为原先数组的1.5倍
  2. 线程不安全
    源码:
private int size;
private static final int DEFAULT_CAPACITY = 10;
1.
public boolean add(E e) {
   	ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

2.
private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);//二者取最大值
    }

    ensureExplicitCapacity(minCapacity);
}

3.
private void ensureExplicitCapacity(int minCapacity) {
   modCount++;

   // overflow-conscious code
   if (minCapacity - elementData.length > 0)
       grow(minCapacity);
}

4.
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);
    }
2. Vector: JDK1.0
  1. 数组实现
    1.1 初始化策略:当产生Vector对象时,内部数组就初始化为大小为10的数组(不管用不用)
    1.2 扩容:每次扩容为原先数组的2倍。
  2. 线程安全性:使用synchronized同步方法来确保线程安全性。
    但是因为使用了synchronized同步方法所以效率会很低(读写互斥)(锁的是当前整个Vector对象,操作任意一个方法,其他线程全部阻塞了,无法实现多个线程同时读这个Vector对象)
  3. 特殊点:JDK内置的Stack继承Vector。Java中自定义的栈是它的子类。
  4. Vector独有枚举输出。
    源码:
1.
public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
        this.capacityIncrement = capacityIncrement;
    }

2.
public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }

3.
private void ensureCapacityHelper(int minCapacity) {
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

4.
private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
    
3.LinkedList: JDK1.2
  1. 基于双向链表的动态数组(所以不存在初始化,扩容问题)
  2. 线程不安全
  3. 特殊:JDK Queue(队列)的一个实现子类
    在这里插入图片描述在这里插入图片描述.
4.ArrayList与LinkedList的选择:

ArrayList 适合查找(取得)和更改
LinkedList 适合增加(插入)删除

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我顶得了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值