容器-集合框架

在数学世界中,集合是指具有某种特性性质的事物汇成的集体,对应的英文是Set,它具有确定性,无序性,互异性等特点。而Java中的集合是用于存储对象的工具类容器,它实现了常用的数据结构,提供了一系列公开的方法用于增加,删除,修改,遍历和查找数据。

框架图主要分为两类:第一类是按照单个元素存储的Collection;第二类是按照Key-Value存储的Map。

Collection接口

Collection接口是java集合框架的根接口,它继承了Iterable接口,提供元素遍历的功能。对于集合框架而言,这个接口定义了集合基本的操作,包括添加、删除、判断是否有元素、清空等:

MethodDescription
boolean add(E a)确保此集合包含指定的元素(可选操作)
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<E> iterator()返回集合的迭代器
default Spliterator<T> spliterator()返回集合的Spliterator
default void forEach(Consumer<? super E>action)对Iterable的每个元素执行给定的操作,直到所有元素都被处理或动作引发异常。 除非实现类另有规定,否则按照迭代的顺序执行操作(如果指定了迭代顺序)
boolean remove(Object o)从该集合中删除指定元素的单个实例(如果存在)(可选操作)
boolean removeAll(Collection<?>c)删除指定集合中包含的所有此集合的元素(可选操作)
default boolean removeIf(Predicate<? extends E>filter)删除满足给定谓词的此集合的所有元素
boolean retainAll(Collection<?> c)仅保留此集合中包含在指定集合中的元素(可选操作)
int size()返回此集合中的元素数
Object[] toArray()返回一个包含此集合中所有元素的数组
<T>T[] toArray(T[] a)返回包含此集合中所有元素的数组; 返回的数组的运行时类型是指定数组的运行时类型
default Stream<E> Stream()返回以此集合作为源的Stream
default Stream<E> parallelStream()返回可能并行的以此集合作为源的Stream

 

如果实现Collection接口的每一个类都要提供如此多的例行方法是一件很烦人的事情。Java类库提供一个类AbstractCollection,它将基础方法size和iterator抽象化,但是在此提供例行方法。

List集合

List集合是线性数据结构的主要实现,集合元素通常存在明确的上一个和下一个元素,也存在明确的第一个元素和最后一个元素。List集合存储一组不唯一(可以有多个元素引用相同对象)的有序对象。该类常用的是ArrayList和LinkedList两个集合类。

ArrayList和LinkedList的区别:

  • 1. 是否保证线程安全: ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全;

  • 2. 底层数据结构: Arraylist 底层使用的是 Object 数组LinkedList 底层使用的是 双向链表 数据结构

  • 3. 插入和删除是否受元素位置的影响: ① ArrayList 采用数组存储,所以插入和删除元素的时间复杂度受元素位置的影响。 比如:执行add(E e)方法的时候, ArrayList 会默认在将指定的元素追加到此列表的末尾,这种情况时间复杂度就是O(1)。但是如果要在指定位置 i 插入和删除元素的话(add(int index, E element))时间复杂度就为 O(n-i)。因为在进行上述操作的时候集合中第 i 和第 i 个元素之后的(n-i)个元素都要执行向后位/向前移一位的操作。 ② LinkedList 采用链表存储,所以插入,删除元素时间复杂度不受元素位置的影响,都是近似 O(1)而数组为近似 O(n)。

  • 4. 是否支持快速随机访问: LinkedList 不支持高效的随机元素访问,而 ArrayList 支持。快速随机访问就是通过元素的序号快速获取元素对象(对应于get(int index)方法)。

  • 5. 内存空间占用: ArrayList的空 间浪费主要体现在在list列表的结尾会预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗比ArrayList更多的空间(因为要存放直接后继和直接前驱以及数据)。

由数组支持的有序集合可以快速地随机方法,因此适合使用List方法并提供一个整数索引来访问(get(index))。与之不同的是,链表尽管有序,但是随机访问很慢,最好使用迭代器进行访问。为了避免对链表完成随机访问操作,引入了一个标记接口RandomAccess。这个接口不包含任何方法。可以用它来测试一个特定的集合是否支持高效的随机访问。

public interface RandomAccess { }

在 binarySearch()方法中,它要判断传入的list 是否 RamdomAccess 的实例,如果是,调用indexedBinarySearch()方法,如果不是,那么调用iteratorBinarySearch()方法

    public static <T>
    int binarySearch(List<? extends Comparable<? super T>> list, T key) {
        if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
            return Collections.indexedBinarySearch(list, key);
        else
            return Collections.iteratorBinarySearch(list, key);
    }

ArrayList 实现了 RandomAccess 接口, 而 LinkedList 没有实现。为什么呢?我觉得还是和底层数据结构有关!ArrayList 底层是数组,而 LinkedList 底层是链表。数组天然支持随机访问,时间复杂度为 O(1),所以称为快速随机访问。链表需要遍历到特定位置才能访问特定位置的元素,时间复杂度为 O(n),所以不支持快速随机访问。,ArrayList 实现了 RandomAccess 接口,就表明了他具有快速随机访问功能。 RandomAccess 接口只是标识,并不是说 ArrayList 实现 RandomAccess 接口才具有快速随机访问功能的!

Queue集合

Queue(队列)是一种先进先出数据结构,队列是一种特殊的线性表,只允许在表的一端进行获取操作,在表的另一端进行插入操作。

Map集合

Map集合是以Key-Value键值对作为存储元素实现的哈希结构,Key按照某种哈希函数计算后是唯一的,Value是可以重复的。Map指向Collection的箭头仅表示两个类的依赖关系。

Set集合

Set是不允许出现重复元素的集合类型,Set体系最常用的是HashSet,TreeSet和LinkedHashSet三个集合类。

  • HashSet从源码分析是使用HashMap来实现的,只是Value固定为一个静态对象,使用Key保证集合元素的唯一性,但它不保证集合元素的顺序。
  • TreeSet从源码分析是使用TreeMap实现的,底层为树结构,在添加新元素到集合时,按照某种比较原则将其插入合适的位置,保证插入后的集合任然是有序的。
  • LinkedHashSet继承自HashSet,具有HashSet的优点,内部使用链表维护了元素插入顺序。

迭代器

Iterator接口包含四个方法:

public interface Iterator<E>
{
    E next();
    boolean hasNext();
    void remove();
    default void forEachRemaining(Consumer<? super E> action);
}

查看集合中的元素:

  • hasNext()和next()一起用。
  • for each循环,编译器将for each循环翻译为带有迭代器的循环。
  • 可以调用forEachRemaining方法并提供一个lambda表达式(它会处理一个元素)。对迭代器的每个元素调用这个lambda表达式,直到再没有元素为止。
iterator.forEachRemaining(element->do something with element);

参考文章:

https://snailclimb.top/JavaGuide/#/java/collection/Java%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98?id=arraylist-%e4%b8%8e-linkedlist-%e5%8c%ba%e5%88%ab

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值