Java集合框架概述(一)——List接口要点详述

一、集合框架概要

  • 集合(Collection):集合是对象的容器,存储对象的对象,可代替数组。·集合也是容器的工具类,定义了多个对象进行操作的方法。

  • 框架(Framework):框架是一组类和接口

  • Collection体系集合

图片资源来源于:https://www.javastudypoint.com/2019/02/collection-framework-in-java.html

Alt

Collection体系集合

二、Collection接口

1.概要

  • Collection: 根接口代表一组对象,称为“集合”;

 Collection接口的“能力”是存储一组对象。 一些集合允许重复元素,而其他集合不允许。 有些被命令和其他无序。 JDK不提供此接口的任何直接实现:它提供了更具体的子接口的实现,如Set和List 。 该界面通常用于传递集合,并在需要最大的通用性的情况下对其进行操作。

2.方法:

Modifier and Type n Method and Descriptio
boolean add(E e) 确保此集合包含指定的元素(可选操作)。
boolean addAll(Collection<? extends E> c) 将指定集合中的所有元素添加到此集合(可选操作)。
void clear() 从此集合中删除所有元素(可选操作)。
boolean contains(Object o) 如果此集合包含指定的元素,则返回 true 。
boolean containsAll(Collection<?> c) 如果此集合包含指定 集合中的所有元素,则返回true。
boolean equals(Object o) 将指定的对象与此集合进行比较以获得相等性。
int hashCode() 返回此集合的哈希码值。
boolean isEmpty() 如果此集合不包含元素,则返回 true 。
Iterator iterator() 返回此集合中的元素的迭代器。
default Stream parallelStream() 返回可能并行的 Stream与此集合作为其来源。
boolean remove(Object o) 从该集合中删除指定元素的单个实例(如果存在)(可选操作)。
boolean removeAll(Collection<?> c) 删除指定集合中包含的所有此集合的元素(可选操作)。
default boolean removeIf(Predicate<? super E> filter) 删除满足给定谓词的此集合的所有元素。
boolean retainAll(Collection<?> c) 仅保留此集合中包含在指定集合中的元素(可选操作)。
int size() 返回此集合中的元素数。
default Spliterator spliterator() 创建一个Spliterator在这个集合中的元素。
default Stream stream() 返回以此集合作为源的顺序 Stream 。
Object[] toArray() 返回一个包含此集合中所有元素的数组。
T[] toArray(T[] a) 返回包含此集合中所有元素的数组; 返回的数组的运行时类型是指定数组的运行时类型。

三、List接口在这里插入图片描述

1.概要

  • List接口: 有序、有下标、元素可重复;
     有序集合(也称为序列 )。 该界面的用户可以精确控制列表中每个元素的插入位置。 用户可以通过整数索引(列表中的位置)访问元素,并搜索列表中的元素。
     与Set不同,列表通常允许重复的元素。 更正式地,列表通常允许元素e1和e2成对使得e1.equals(e2) ,重复元素的定义根据用户定义的equals来决定。并且如果它们允许null元素,它们通常允许多个null元素。

2.部分方法:

Modifier and Type Method and Descriptio
boolean add(E e) 在index位置插入。
boolean addAll(int index ,Collection c) 将集合中的元素添加到此集合中的index位置
E get(int index) 返回此列表中指定位置的元素。
List subList(int fromIndex, int toIndex) 返回此列表中指定的 fromIndex (含)和 toIndex之间的集合元素。

3.ArrayList

概要:

 从JDK1.2 版本开始。ArrayList是可调整大小的数组实现List接口的类。 实现所有可选列表操作,并允许所有元素,包括null 。 除了实现List 接口之外,该类还提供了一些方法来操纵内部使用的存储列表的数组的大小。 (这个类是大致相当于Vector,不同之处在于它是不同步的)。

构造方法

构造方法 描述
ArrayList() 构造一个初始容量为0的空列表。
ArrayList(Collection<? extends E> c) 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。
ArrayList(int initialCapacity) 构造具有指定初始容量的空列表。
  • ArrayList什么结构实现?有什么特点?为什么?

 数组结构实现,查询快、增删慢;
 在ArrayList中增加或者是删除元素,要调用System.arraycopy这种效率很低的操作,如果遇到了需要频繁插入或者是删除的时候,你可以选择其他的Java集合,比如LinkedList。

  • ArrayList的初始值和Add方法的实现

 初始容量:jdk1.6的时候初始值是10,jdk1.7之后,初始容量是0,不占内存空间,只有当第一次添加的时候再去分配空间;这样有利于空间的节省和利用;

jdk 1.8:(注释为10,但是实际上DEFAULTCAPACITY_EMPTY_ELEMENTDATA被定义的是一个空数组)

/**
 * Constructs an empty list with an initial capacity of ten.
 */
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

实际上怎么分配空间的呢?
 只有当第一次添加的时候,数组开始按照扩容加一的方式进行扩容

private int size;

public boolean add(E e) {
     ensureCapacityInternal(size + 1);  // Increments modCount!!
     elementData[size++] = e;
     return true;
 }
  • ArrayList怎样确保容量的大小呢?

参考链接:https://www.cnblogs.com/softidea/p/6410680.html

 事实上,当用户试图在arraylist中增加一个对象的时候,Java会去检查arraylist,以确保已存在的数组中有足够的容量来存储这个新的对象。如果没有足够容量的话,那么就会新建一个长度更长的数组,旧的数组就会使用Arrays.copyOf方法被复制到新的数组中去,现有的数组引用指向了新的数组。

private static final int DEFAULT_CAPACITY = 10;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

public void ensureCapacity(int minCapacity) {
    int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
        // any size if not default element table
        ? 0
        // larger than default for default empty table. It's already
        // supposed to be at default size.
        : DEFAULT_CAPACITY;

    if (minCapacity > minExpand) {
        ensureExplicitCapacity(minCapacity);
    }
}
private void ensureExplicitCapacity(int minCapacity) {
   modCount++;

   // overflow-conscious code
   if (minCapacity - elementData.length > 0)
       grow(minCapacity);
}
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);
}

4、Vector

概要:

 从JDK1.0 版本开始。Vector类实现了可扩展的对象数组。 像数组一样,它包含可以使用整数索引访问的组件。 但是, Vector的大小可以根据需要增长或缩小,以适应在创建Vector之后添加和删除项目。

构造方法

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

Vector与ArrayList差异比较与分析

目前基本很少使用Vector,开发过程中基本使用的是ArrayList;
ArrayList:

  • 数组结构实现,查询快,增删慢
  • JDK1.2版本。运行效率快,线程不安全

Vector

  • 数组结构实现,查询快,增删慢
  • JDK1.0版本。运行效率慢,线程安全
    从 add方法分分析原因
public synchronized boolean add(E e) {
    modCount++;
    ensureCapacityHelper(elementCount + 1);
    elementData[elementCount++] = e;
    return true;
}

 与之前的ArrayList的add方法作比较,Vector是一个一个“排队”加入数组,而ArrayList是几个几个“不排队”加入数组。

效率高但是线程不安全

5、LinkedList

链表实现,查询慢、增删快

LinkedList与ArrayList差异比较与分析

线性表——查询快、增删慢

 线性表在内存中是一块连续的存储空间,只要知道了该对象 相对 数组的第一个对象在内存中所在的位置,然后根据下标移动指定次数,就可以很容易的知道其他元素的位置。

  • 优点:因为只需要查看第一个对象,所以,在线性表中访问数据元素是很快的。
  • 缺点:因为它是连续的一块内存空间,如果说数组的第一个对象没有占满所分配的空间,剩余空间有不足以容纳数组的第二个对象,那么只好另外分配新的内存空间;因为是连续性的,在执行增加或删除操作时,数组中所有的对象的位置都需要改变。

链表——查询慢、增删快

 链表在内存中不是一块连续的存储空间,只有知道该元素上一元素的位置才能确定该元素的位置,它们只有二者之间的关联。

  • 优点:可以复用你的零散空间,零散内存;因为是指向性的,所以在增加或删除元素的时候只需要改变该对象前后的指向关系即可
  • 缺点:我们如果需要查数组中的第n个对象,那么需要把n-1个对象都浏览一遍。n越大效率越低。
    在这里插入图片描述
     但是对于LinkedList而言,访问头和尾的速度是最快的,与ArrayList不相上下,因此,LinkedList也单独定义了两个方法:addFirst()、addLast()、getFirst()、getLast()…等
方法 描述
void addFirst(E e) 在该列表开头插入指定的元素。
void addLast(E e) 将指定的元素追加到此列表的末尾。
E getFirst() 返回此列表中的第一个元素。
E getLast() 返回此列表中的最后一个元素。

 因此在使用的时候,如果集合用到的查询远大于增删,我们选择使用ArrayList;相反,则使用LinkedList

发布了82 篇原创文章 · 获赞 124 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/qq_44717317/article/details/104631940
今日推荐