集合详解—List接口

List接口

|----Collection接口:单列集合,用来存储一个一个的对象
         |----List接口:存储有序的、可重复的数据。  -->“动态”数组,替换原有的数组
             |----ArrayList:作为List接口的主要实现类;线程不安全的,效率高;底层使用Object[] elementData存储              		|----LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用双向链表存储
    		 |----Vector:作为List接口的古老实现类;线程安全的,效率低;底层使用Object[] elementData存储

List除了从Collection集合继承的方法外,List 集合里添加了一些根据索引来操作集合元素的方法。

方法 描述
void add(int index, Object ele) 在index位置插入ele元素
boolean addAll(int index, Collection eles) 从index位置开始将eles中的所有元素添加进来
Object get(int index) 获取指定index位置的元素
int indexOf(Object obj) 返回obj在集合中首次出现的位置
int lastIndexOf(Object obj) 返回obj在当前集合中末次出现的位置
Object remove(int index) 移除指定index位置的元素,并返回此元素
Object set(int index, Object ele) 设置指定index位置的元素为ele
List subList(int fromIndex, int toIndex) 返回从fromIndex到toIndex位置的子集合

List接口的实现类之一:ArrayList

ArrayList 是 List 接口的典型实现类、主要实现类

  • 本质上,ArrayList是对象引用的一个”变长”数组
  • Arrays.asList(…) 方法返回的 List 集合,既不是 ArrayList 实例,也不是Vector 实例。 Arrays.asList(…) 返回值是一个固定长度的 List 集合

ArrayList的JDK1.8之前与之后的实现区别?

jdk 7:
	ArrayList list = new ArrayList();//底层创建了长度是10的Object[]数组elementData
      	list.add(123);//elementData[0] = new Integer(123);
      	...
      	list.add(11);//如果此次的添加导致底层elementData数组容量不够,则扩容。
      	默认情况下,扩容为原来的容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中。

      	结论:建议开发中使用带参的构造器:ArrayList list = new ArrayList(int capacity)
jdk 8:
	ArrayList list = new ArrayList();//底层Object[] elementData初始化为{}.并没有创建长度为10的数组		
		list.add(123);//第一次调用add()时,底层才创建了长度10的数组,并将数据123添加到elementData[0]
        ...
        后续的添加和扩容操作与jdk 7 无异。

List接口的实现类之二:LinkedList

对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高

新增方法:

  • void addFirst (Object obj)
  • void addLast(Object obj)
  • Object getFirst()
  • Object getLast()
  • Object removeFirst()
  • Object removeLast()

LinkedList:双向链表,内部没有声明数组,而是定义了Node类型的first和last,用于记录首末元素。同时,定义内部类Node,作为LinkedList中保存数据的基本结构。Node除了保存数据,还定义了两个变量:

  • prev变量记录前一个元素的位置
  • next变量记录下一个元素的位置
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;
    }
}

List接口的实现类之三:Vector

Vector 是一个古老的集合,JDK1.0就有了。大多数操作与ArrayList相同,区别之处在于Vector是线程安全的。

在各种list中,最好把ArrayList作为缺省选择。当插入、删除频繁时,使用LinkedList;Vector总是比ArrayList慢,所以尽量避免使用。

新增方法:

  • void addElement(Object obj)
  • void insertElementAt(Object obj,int index)
  • void setElementAt(Object obj,int index)
  • void removeElement(Object obj)
  • void removeAllElements()

面试题:

请问ArrayList/LinkedList/Vector的异同?谈谈你的理解?ArrayList底层是什么?扩容机制?Vector和ArrayList的最大区别?
 
ArrayList和LinkedList的异同
二者都线程不安全,相对线程安全的Vector,执行效率高。
此外,ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。对于新增和删除操作add(特指插入)和remove,LinkedList比较占优势,因为ArrayList要移动数据。

ArrayList和Vector的区别
Vector和ArrayList几乎是完全相同的,唯一的区别在于Vector是同步类(synchronized),属于强同步类。因此开销就比ArrayList要大,访问要慢。正常情况下,大多数的Java程序员使用ArrayList而不是Vector,因为同步完全可以由程序员自己来控制。Vector每次扩容请求其大小的2倍空间,而ArrayList是1.5倍。Vector还有一个子类Stack。

猜你喜欢

转载自blog.csdn.net/qq_44346427/article/details/110729382