集合


Java集合体系结构

在这里插入图片描述

collection接口下:List接口(有序[存储顺序],元素可重复)和Set接口(无需,元素不可重复)
Collection接口和Map接口:Map是对Collection的补充,两个没有什么关系
Collection存储是单个值 Map存储是<K,V>键值对
List接口的实现类:ArrayList、LinkedList、Vector
Set接口的实现类:HashSet、TreeSet、LinkedHashSet
Map接口的实现类:HashMap、TreeMap、Hashtable


Collection

Collection是所有单列集合的顶层接口,在Java中存在的有序集合(List)和无序集合(Set)都从Collection接口继承,Collection中常用的方法:

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)
返回包含此集合中所有元素的数组; 返回的数组的运行时类型是指定数组的运行时类型。

由于Collection是一个顶层接口,因此对于不同类型的集合也存在两个子接口分别进行处理

  • List:是一个有序的集合,并且允许重复的元素出现
  • Set:是一个无序的集合,并且不允许重复元素的出现

面试题:
Collection、Collections、Connection什么区别?
Collection是所有单列集合的顶层接口;
Collections是针对集合进行处理的工具类,比如排序、查找、洗牌、逆序等操作;
Connection是Java访问数据库技术(JDBC)中的数据库连接对象的顶层接口

List接口

  • 继承Collection接口
  • 有序集合(存储元素的顺序和取出元素的顺序一致,可以通过索引位访问元素)
  • 可重复
  • 在Collection接口上新增一些方法

void add(int index, E element)
将指定的元素插入此列表中的指定位置(可选操作)。
boolean addAll(int index, Collection<? extends E> c)
将指定集合中的所有元素插入到此列表中的指定位置(可选操作)。
int indexOf(Object o)
返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。
int lastIndexOf(Object o)
返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。
E remove(int index)
删除该列表中指定位置的元素(可选操作)。
E set(int index, E element)
用指定的元素(可选操作)替换此列表中指定位置的元素。
E get(int index)
返回此列表中指定位置的元素。
List subList(int fromIndex, int toIndex)
返回此列表中指定的 fromIndex (含)和 toIndex之间的视图。

List接口常见实现类

ArrayList
LinkedList
Vector

ArrayList

  • 底层通过数组实现
  • 数组初始容量为10(不是new就是10,在第一次执行add方法的时候)
    底层代码可见
  • 内部通过数组拷贝实现扩容,当容量超出时,会扩容为原来的1.5倍
  • 线程不安全(不同步)JDK1.5版本设计一个CopyOnWriteArrayList
  • 数组一旦创建不能改变,因此在非末端插入和删除数据到时候,由于可能设计到数组拷贝问题,因此修改和删除效率比较低。

LinkedList

  • 底层通过双向链表实现
    元素是通过首尾指针连接,在进行修改(新增、删除)元素的时候只需要修改指针即可,一般情况下修改效率要比ArrayList高,但是在查询时,LinkedList比ArrayList效率低,链表从第一个元素开始依次向后搜索。
  • 比较适合数据的动态插入和删除
  • 随机访问和遍历速度比较慢

Vector

  • 底层通过数组实现,早期集合类JDK1.0
  • 线程安全(关键方法上使用synchronized修饰)
  • 已淘汰-单线程环境建议使用ArrayList,多线程环境建议使用CopyOnWriteArrayList
  • Vector在容量扩容时,增长为原来的2倍

Vector、LinkedList、ArrayList区别?

  • Vector是老式的集合类,内部基于动态数组实现,容量扩充为原来的2倍,Vector是线程安全的实现
  • ArrayList是JDK1.2之后新增的List集合的实现,内部也是基于动态数组实现,容量扩充为原来的1.5倍,ArrayList是线程不安全的实现(效率高),数据查询较快,修改较慢
  • LinkedList是JDK1.2之后新增的List集合的实现,内部是基于双向链表的实现,也是线程不安全的实现,在进行数据修改方面比较快,数据查询比较慢

Set接口

  • 元素的存储顺序与添加顺序无关(无序)
  • 内部不允许重复元素

Set由于是一个接口,因此对于该接口,集合框架内部提供了一些常见的实现类:

  • HashSet
  • LinkedHashSet
  • TreeSet
    常用方法:

add(Object obj) 向集合中添加元素
addAll(Collection c) 将一个集合添加到当前集合中
clear() 清除集合中所有元素
isEmpty() 判断集合是否为空集合(size = 0)
remove(Object obj) 删除指定元素
iterator() 获取当前集合的迭代器对象
size() 获取集合中元素个数

HashSet

HashSet是基于哈希表的实现(内部实际就是一个HashMap),内部的元素存储根据调用元素的hashCode方法实现,由于对象的存储基于hashCode算法,因此如果多个对象的hashCode值一致,则集合中只会存储一个(在重写hashCode方法时,也必须要同时重写equals

TreeSet

TreeSet内部实现原理是基于二叉树中的红黑树实现,使用TreeSet的前提:

  • 元素必须是同一种数据类型
  • 元素必须实现过Comparable接口

注意事项:

  • TreeSet内部对于多个元素的去除重复根据重写的comparaTo方法来决定的,如果多个对象comparaTo方法返回值是一致的,则集合只会存储一个
  • TreeSet中的元素对象的类如果未实现Comparable接口,则会抛出运行时异常
    java.lang.ClassCastException
    因为内部会将元素强制转换成Comparable对象

LinkedHashSet

HashSet是基于hash算法实现的元素的存储,但是由于不同的对象hash值存在差异,因此元素的存储顺序不一定按添加顺序来;在实际的开发中如果需要按照元素的添加顺序存贮,并且保证元素不重复,因此可以使用由Set集合提供的另一个实现:LinkedHashSet;
LinkedHashSet是从HashSet继承而来,内部的实现原理是基于LinkedHashMap

面试题:
HashSet,TreeSet和LinkedHashSet区别?

  • HashSet是Set集合基于hash表(散列表)的实现元素存储,内部的元素存储顺序跟hash值有关,如果多个对象的hash一致(equals也一致)则集合会认为是重复元素,因此不会加入集合中;HashSet内部实现原理是基于HashMap的。
  • TreeSet是Set集合基于红黑树(二叉排序树中的特殊平衡二叉树),内部元素的存储顺序是根据元素对应类实现的Comparable接口中compareTo方法进行存储,如果多个对象的comparaTo方法返回值一致,则TreeSet会认为是重复元素,因而不会重复存储;TreeSet实际就是基于TreeMap的实现
  • LinkedHashSet是HashSet的子类,内部基于单链表的实现,元素的存储顺序按照添加顺序来存储,是一个有序的set集合;内部实现原理使用了LinkedHashMap。

Map

之前所学习到的List集合以及Set集合都是直接从Collection继承而来的单列子集合,另外,java的集合框架中也提供了另一种特殊的集合接口:双列集合:Map;

Map集合是由键值对结构组成,通常由一个唯一键对应一个值,集合中存储的元素键不允许重复,但是值可以重复,Map集合是一个键值对集合的顶层接口,常见的实现类主要有以下:

  • HashMap
  • TreeMap
  • LinkeHashMap
  • ConcurrentHashMap

虽然Map集合是一个键值对结构,但是实际内部存储的每一个元素都是一个Entry对象,而Entry内部包含两个属性,一个是Key,另一个是Value

常见方法:

  • clear() 清除Map集合中的所有元素
  • containsKey(Object key) 判断集合中是否包含指定的键
  • containsValue(Object value) 判断集合中是否包含指定的值
  • entrySet() 返回当前Map集合中Entry的Set集合
  • get(Object key) 根据键获取值
  • put(Object k,Object v) 向集合中添加元素(键值对)
  • keySet() 获取键的Set集合
  • remove(Object key) 根据键删除指定的元素
  • size() 返回该Map集合中元素的个数
  • values() 返回Map集合中所有的值集合(Collection)

HashMap

HashMap是Map中最常用的一个实现类,内部实现是基于数组+链表(JDK1.8之前;JDK1.8之后改为使用数组+链表+红黑树实现);元素的存储按照键值对的方式,存储顺序根据键的hashCode(包括equals)计算之后存储

HashMap的初始容量是16,默认的加载因子是0.75(降低hash碰撞的概率),HashMap的扩容方式为原来的2倍;实现原理:

  • 在1.8之前使用的是数组和链表实现,默认情况下通过计算元素的hash值,然后和16取余(实际: hash & (length-1)),再根据计算结果将元素(Map.Entry)存储对应的数组中,如果该位置已经存在元素,则此时引入链表,采用头插法将最新的元素插入到链表头部。
  • 在JDK1.8之后使用数组+链表+红黑树(平衡排序二叉树)实现,红黑树的加入有特定前提
    • 数组的长度必须超过64
    • 链表深度必须大于8

TreeMap

Map集合另外针对于排序的需求还有一个TreeMap的实现类,该类内部基于红黑树(平衡排序二叉树)实现;内部的元素存储顺序,由键对应的类型实现Comparable接口后,通过重写comparaTo方法实现;TreeMap的使用需要满足以下两个条件:

  • key的类型必须一致
  • key对应的类必须实现Comparable接口

TreeMap不允许空键出现

Hashtable

Hashtable也是键值对结构的集合解决方案,从jdk1.0之后就已经存在,从老式的集合类java.util.Dictionary继承而来,初始长度是11(HashMap是16),Hashtable是线程安全实现(HashMap是线程不安全的实现);Hashtable不允许空键值出现(HashMap允许)

LinkedHashMap

LinkedHashMap是基于链表的HashMap实现,本身也是从HashMap继承而来,通过链表实现内部元素的存储顺序保持与添加顺序一致。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值