Java容器-单例集合

1.容器简介

容器类似于显示生活中的锅碗瓢盆,可以存放东西。
在Java中,数组可以用来存放基本类型数据或者对象,但是随着深入的学习,数组的弊端也显现出来了,不能随着需求变化尽心扩容。所以实际中我们其实使用集合(Collection)来装载我们的对象。

2.单例集合

2.1 基本介绍

将数据一个一个的进行存储。
image

2.2 Collection接口

是单例集合根接口,继承自超级接口Iterator,定义了所有单例集合的共性接口。

方法

基本方法

  • int size();
  • boolean isEmpty();
  • boolean contains(Object element); 是否包含指定元素
  • boolean add(E element); 添加元素,成功时返回 true
  • boolean remove(Object element); 删除元素,成功时返回 true
  • Iterator iterator(); 获取迭代器

操作集合的方法

  • boolean containsAll(Collection<?> c) ;
    是否包含指定集合 c 的全部元素
  • boolean addAll(Collection<? extends E> c) ;
    添加集合 c 中所有的元素到本集合中,如果集合有改变就返回 true
  • boolean removeAll(Collection<?> c) ;
    删除本集合中和 c 集合中一致的元素,如果集合有改变就返回 true
  • boolean retainAll(Collection<?> c) ;
    保留本集合中 c 集合中两者共有的,如果集合有改变就返回 true
  • void clear() ;
    删除所有元素

操作集合变数组的方法

  • Object[] toArray() ;
    返回一个包含集合中所有元素的数组
  • T[] toArray(T[] a) ;
    返回一个包含集合中所有元素的数组,运行时根据集合元素的类型指定数组的类型

2.3 List接口

继承Collection接口,有几个特点

  • 有序
  • 可重复
  • 可以存储null值
  • 有索引,针对每个元素可以快速的查询和修改

方法

增加

  • void add(int index, E element)
    在指定 index 索引处理插入元素 element
  • boolean addAll(int index, Collection<? extends E> c) 在指定 index 索引处理插入集合元素 c

删除

  • E remove(int index)
    删除指定索引 index 处的元素

修改

  • E set(int index, E element)
    修改指定索引 index 处的元素为 element

获取

  • E get(int index)
    获取指定索引处的元素
  • int indexOf(Object o)
    从左往右查找,获取指定元素在集合中的索引,如果元素不存在返回 -1
  • int lastIndexOf(Object o)
    从右往左查找,获取指定元素在集合中的索引,如果元素不存在返回 -1
  • List subList(int fromIndex, int toIndex)
    截取从 fromIndex 开始到 toIndex-1 处的元素

遍历

  • ListIterator listIterator()
    通过列表迭代器遍历集合中的每一个元素
  • ListIterator listIterator(int index)
    通过列表迭代器从指定索引处开始正向或者逆向遍历集合中的元素

2.3.1 ArrayList

ArrayList 是 List 接口的实现类。是 List 存储特征的具体实现。
ArrayList 底层是用数组实现的存储。 特点:查询效率高,增删效率低,线程不安全。

实例

点击查看代码
public static void main(String[] args) {
		List<String> a = new ArrayList<>();
		a.add("aa");
		a.add("bb");//添加元素
		for (int i = 0; i < a.size(); i++) {
			System.out.println(a.get(i));//获取指定索引出的元素
		}
		String first = a.get(0); //获取指定索引出的元素
		a.remove(0);//删除指定位置的元素
		a.remove("aa");//删除指定元素
		String second = a.set(1,"cc");//替换指定索引的元素
		a.clear();//清空容器
		boolean isEmpty = a.isEmpty();//判断容器是否为空
		boolean flag = a.contains("aa");//判断列表中是否包含指定的元素
		int flag1 = a.indexOf("aaa");//判断指定元素第一次出现的位置
		int flag2 = a.lastIndexOf("aaa");//判断指定元素最后一次出现的位置
		Object[] flag3 = a.toArray();//单例集合转化为object数组
		String[] flag4 = a.toArray(new String[a.size()]);//转换泛型类型数组
		
		List<String> b = new ArrayList<>();
		b.add("bb");
		b.add("cc");
		boolean flag5 = a.addAll(b);//取并集
		boolean b1 = a.retainAll(b);//取交集
		a.removeAll(b);//取差集
	}

源码分析

底层是用数组实现的存储
image
无参构造初始化,是一个空数组
image
当调用add()方法时会对数组先进行扩容
image
容量检查,确认数组是否需要扩容
image
数组的扩容逻辑(1.5倍)
image

2.3.2 VecTor

Vector 底层是用数组实现的,相关的方法都加了同步检查,因此“线程安全,效率低”。 比如,indexOf 方法就增加了 synchronized 同步标记。
例如
image

源码分析

初始化的时候定义了数组长度
image
判断是否需要扩容
image
扩容逻辑
image

2.3.3 LinkedList

LinkedList底层用双向链表实现的存储。特点:查询效率低,增删效率高,线程不安全。
双向链表也叫双链表,它的每个数据节点都有两个指针,分别指向前一个结点和后一个节点。所以从双向表的任意一个节点开始,都可以方便的找到所有的节点。

class Node{ E item; Node<E> next; Node<E> prev; }

方法(扩展List):

  • void addFirst(E e) 将指定元素插入到开头
  • void addLast(E e) 将指定元素插入到结尾
  • getFirst() 返回此列表的第一个元素
  • getLast() 返回此列表的最后一个元素
  • removeFirst() 移除此列表中的第一个元素,并返回这个元素
  • removeLast() 移除此列表中的最后一个元素,并返回这个元素
  • E pop() 从此列表所表示的堆栈处弹出一个元素,等效于removeFirst
  • void push(E e) 将元素推入此列表所表示的堆栈 这个等效于 addFisrt(E e)
  • boolean isEmpty() 判断列表是否包含元素,如果不包含元素则返回 true

源码分析

节点类
image
成员变量
image
添加元素

  1. 头尾添加元素,直接改变头尾的指针引用
    image
  2. 指定位置添加元素,先判断是否抛异常,接着找到当前位置节点,最后插入节点
    image
    image
    image

获取元素

image
image

删除元素
image
image

2.4 Set

Set接口继承自Collection,Set接口中没有新增方法,意味着和Collection保持一致。
常用的实现类有:HashSet、TreeSet等。

特点

  • 无序, Set 中的元素没有索引,我们只能遍历查找.
  • 不可重复,不允许加入重复的元素。更确切地讲,新元素如果和 Set 中某个元素通过 equals() 方法对比为 true,则只能保留一个(需要自定义HashCode和equals方法)。

2.4.1 HashSet

特征

  1. 无序
    HashSet 是一个没有重复元素的集合,不保证元素的顺序。在 HashSet 中底层是使用 HashMap 存储元素的。HashMap 底层使用的是数组与链表实 现元素的存储。元素在数组中存放时,并不是有序存放的也不是随机存放的,而是对元素的哈希值进行运算决定元素在数组中的位置。
  2. 不重复
    当两个元素的哈希值进行运算后得到相同的在数组中的位置时,会调用元素的 equals() 方法判断两个元素是否相同。如果元素相同则不会添加该元素,如果不相同则会使用单向链表保存该元素。

源码

成员变量,底层使用的HashMap
image
使用过程中,HashMap中的value是没有使用到的,存的是一个空对象。
image

2.4.2 TreeSet

特点

TreeSet 是一个可以对元素进行排序的容器。底层实际是用 TreeMap 实现的,内部维持了一个简化版的 TreeMap,通过 key 来存储 Set 的元素。 TreeSet 内部需要对存储的元 素进行排序,因此,需要给定排序规则。
排序规则实现:

  1. 通过元素自身实现比较规则。
    类需要实现Comparable接口。重写compareTo方法,自定义比较规则。
  2. 通过比较器指定比较规则。
    通过比较器定义比较规则时,需要我们单独创建一个比较器,比较器需要实现Comparator接口的compare方法来定义比较规则,在实例化 TreeSet 时将比较器对象交给 TreeSet 来完成元素的排序处理。此时元素自身就不需要实现比较规则了。
    image

源码

成员变量和构造方法
image
添加元素,只用到了map的key
image

posted @ 2022-01-19 14:38  她与代码皆失  阅读(146)  评论(0)    收藏  举报