java集合之——Collection接口;一文摸清楚collection和它子接口

Collection与其子接口

前言

Collection接口是在整个Java类集中最大的单值操作父接口,它下面还包含一些子类。

所谓单值操作指的是该接口每次只能存储一个数据。


Collection方法

Collection包含的常用方法如下:

No. 方法名称 类型 描述
1 public boolean add(E e) 普通 向集合中插入一个元素
2 public boolean addAll(Collection<? extends E> c) 普通 向集合中插入一组元素
3 public void clear() 普通 清空集合中的元素
4 public boolean contains(Object o) 普通 查找一个元素是否存在
5 public boolean containsAll(Collection<?> c) 普通 查找一组元素是否存在
6 public boolean isEmpty() 普通 判断集合是否为空
7 public Iterator iterator() 普通 为 Iterator 接口实例化
8 public boolean remove(Object o) 普通 从集合中删除一个对象
9 boolean removeAll(Collection<?> c) 普通 从集合中删除一组对象
10 boolean retainAll(Collection<?> c) 普通 判断是否没有指定的集合
11 public int size() 普通 求出集合中元素的个数
12 public Object[] toArray() 普通 以对象数组的形式返回集合中的全部内容
13 T[] toArray(T[] a) 普通 指定操作的泛型类型,并把内容返回
14 public boolean equals(Object o) 普通 从 Object 类中覆写而来
15 public int hashCode() 普通 从 Object 类中覆写而来

我们一般不直接使用Collection接口,而是使用它的两个子接口:List,Set

作为子接口,当然也全部继承Collection的全部方法和特性,比如全部是单值存储。当然有些方法在继承后被重写了。


List接口

List接口的特点是里面存储的内容是允许重复的

定义:
public interface List<E> extends Collection<E>

List接口中的方法

List接口中有如下10个方法是对Collection接口进行扩充:

No. 方法名称 类型 描述
1 public void add(int index,E element) 普通 在指定位置处增加元素
2 boolean addAll(int index,Collection<? extends E> c) 普通 在指定位置处增加一组元素
3 public E get(int index) 普通 根据索引位置取出每一个元素
4 public int indexOf(Object o) 普通 根据对象查找指定的位置,找不到返回-1
5 public int lastIndexOf(Object o) 普通 从后面向前查找位置,找不到返回-1
6 public ListIterator listIterator() 普通 返回 ListIterator 接口的实例
7 public ListIterator listIterator(int index) 普通 返回从指定位置的 ListIterator 接口的实例
8 public E remove(int index) 普通 获取并删除指定位置的内容
9 public E set(int index,E element) 普通 修改指定位置的内容
10 List subList(int fromIndex,int toIndex) 普通 返回子集合

当然,List作为一个接口,必须要用实现类才能实现它的意义。常用的实现类有如下几个:

  1. ArrayList(95%)
  2. Vector(4%)
  3. LinkList(1%)

ArrayList、Vector、LinkList的区别:

  1. ArrayList线程异步、线程不安全,Vector线程同步、线程安全
  2. ArrayList、Vector是基于动态数组的实现,LinkList是基于链表的实现

ArrayList类

前序:

基于数组结构实现,对于操作数据增加删除慢,查找快。

实现

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable

AbstractList是 List 接口的子类。AbstractList 是个抽象类,适配器设计模式。

我们一般实例化对象和指定泛型类型就如下:

ArrayList<Integer> data = new ArrayList<>();

ArrrayList有三种构造方法:

构造器
ArrayList() 构造一个初始容量为10的空列表。
ArrayList(int initialCapacity) 构造具有指定初始容量的空列表。
ArrayList(Collection<? extends E> c) 按照集合的迭代器返回的顺序构造一个包含指定集合元素的列表。

注意:使用ArrayList()构造方法时,初始容量刚开始并不是为10;

刚开始在没存数据之前,其实容量为0,存数据时会进入判断,当前容量1.5倍小于等于当前容量加1时(newCapacity - minCapacity <= 0),如果数组是第一次存入数据,容量就会动态扩展到10;

在以上构造方法中,如果但数据存不下去时,数组长度就会扩展1.5倍(newCapacity = oldCapacity+(oldCapacity >> 1))(>>1:二进制右移一位)


Vector类

前序

从Java1.2开始该类才得以改进实现List接口,使用的也是数组结构;

Vector线程同步某一个时刻只有一个线程能够编写Vector,线程安全但速度慢;

如果不需要线程安全实现,则建议使用ArrayList,速度更快;

实现

public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable

AbstractList是 List 接口的子类。AbstractList 是个抽象类,适配器设计模式。

我们一般实例化对象和指定泛型类型就如下:

Vector<Integer> data = new Vector<>();

构造方法

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

Vector可以指定增量大小,如果增量为0,则扩容算法是翻一番。


Vector 类和 ArrayList 类的区别

这两个类虽然都是 List 接口的子类,但是使用起来有如下的区别,为了方便大家笔试,列出此内容:

No. 区别点 ArrayList Vector
1 时间 是新的类, 是在 JDK 1.2 之后推出的 是旧的类是在 JDK 1.0 的时候就定义的
2 性能 性能较高,是采用了异步处理 性能较低,是采用了同步处理
3 输出 支持 Iterator、ListIterator 输出 除了支持 Iterator、

LinkedList类

前序

LinkedList使用的是双向链表结构,对于增加删除快,查找则慢;

这种类的使用情况非常少;

实现

public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>,Deque<E>, Cloneable, Serializable

此类继承了 AbstractList,所以是 List 的子类。但是此类也是 Queue 接口的子类,Queue 接口定义了如下的方法:

No. 方法名称 类型 描述
1 public boolean add(E e) 普通 增加元素,如果有容量限制,并且已满,则抛出异常
2 public E element() 普通 取得,但是不删除当前元素,如果对列为空则抛出异常
3 boolean offer(E e) 普通 添加,如果有容量限制,并且已满,只是无法添加,但不抛出异常,返回false
4 E peek() 普通 取得头元素,但是不删除,如果队列为空,则返回null
5 E poll() 普通 取得头元素,但是删除, 如果队列为空,则返回 null
6 E remove() 普通 删除当前元素, 如果对列为空则抛出异常

我们一般实例化对象和指定泛型类型就如下:

LinkedList<Integer> data = new LinkList<>();

LinkedList可以用来模拟栈的数据结构
LinkedList<Integer> data = new LinkedList<>();
//压栈
data.push(100);
data.push(200);
//弹栈
Integer i = data.pop();
System.out.println(i);
LinkedList可以用来模拟队列(单端和双端)的数据结构
LinkedList<Integer> data = new LinkedList<>();
data.addFirst(100);
data.addFirst(200);
Integer i = data.removeLast();
System.out.println(i);


Set接口

前言

Set是Collection子接口,与 List 接口最大的不同在于,Set 接口不包含重复元素。
Set 接口并没有对 Collection 接口进行扩充,基本上还是与 Collection 接口保持一致。
在此接口中有两个常用的子类:HashSet、TreeSet


关于Set的元素

Set接口没有 List 接口中定义的 get(int index)方法,所以无法使用循环进行输出。想要获取数据有两个办法:

  1. 使用迭代器进行输出
  2. 使用toArray()转换为数组再进行遍历、输出

Set 接口不包含重复元素,而且为单值,null也只能存在一个。这样的形式可以模拟数学中’集‘的概念;

Set集合有一些子类在存储时散列存放的数据结构,当存储可变对象时需要非常小心,每个数据的位置由该数据计算得到,如果数据可修改,那么地址也会变化。


HashSet类

HashSet属于散列存放,使用哈希表结构进行存储数据。

HashSet<String> set = new HashSet<>();

使用HashSet存数据,其实是借用了HashMap(双值存储)的存储方式,一个值存要存的数据e,另一个值存指定的常量PRESENT;

在这里插入图片描述

HashSet存储元素输出没有规律,而且重复元素无法再次存入;

HashSet<String> set = new HashSet<>();
set.add("a");
set.add("b");
set.add("c");
set.add("a");
Iterator<String> iterator = set.iterator();
while(iterator.hashNext()){
    
    
    System.out.print(iterator.next()+", ");
}
打印结果可能是:a, c, b,

TreeSet类

前序

TreeSet采用二叉树进行存储,是有序的;

内部存储和HashSet一样,是基于Map来存储数据的;

提供的方法和HashSet基本一样,只不过它们存储的数据结构不一样;

TreeSet的使用

TreeSet<String> data = new TreeSet<>();

打印出来的顺序是基于ASCII码进行先后排序的,如果数据不属于ASCII码,比如存储的是对象名,打印顺序就会出乱子。

那不属于的ASCII码的该如何比较呢:那就需要实现Comparable接口。

例如:

在这里插入图片描述
在这里插入图片描述

Guess you like

Origin blog.csdn.net/m0_58702068/article/details/120525705