点击上方「10分钟编程」关注我呦
让我们在一起每天「博学」一点点,成为更好的自己!
集合(Collection)
「为什么要学习集合?」
学习集合,就有必要说一下数组,集合在某种程度上弥补了数组的缺陷。
我们先了解下数组的的特点
❝长度固定,如果加入的元素超过了数组的长度就需要重新定义
可以存储基本数据类型和引用数据类型
数组存储的数据类型是同一类型的
❞
了解了数组,那我们需要了解下「什么是集合?」
Java是一种面向对象的语言,所以就需要一种容器来存放对象,因此,集合就产生了,我们把集合概括为存放对象的容器,它有如下的特点:
❝集合的长度是可变的,它根据元素的添加而增长
集合只能存储引用类型,即使存入的是基本数据类型,它也会包装成引用类型
集合中存储的类型不一定是同一类型。
集合底层的数据结构有数组、链表、栈、树、及多种结构的组合
❞
在Java中,集合主要分为两大类,一类为按单个元素存储的Collection,另一类是按照Key-Value存储的Map,这两类在数据的存取和遍历方式差别非常大,所以文章先讲解Collection,使得我们对Collection的内容有个具体的把控。
1、Collection
本文以JDK1.8为例,Collection接口位于java.util包下,是一个工具接口,根据不同的特点实现了很多工具类,文章主要讲解我们开发中常用的子类及Collection中常用的方法。
「先看着一组继承链」
可以看出,Collection子接口主要有List、Set和Queue三个接口,抽象子类有AbstractSet、AbstractQueue和AbstractList
在继承链中,Collection实现了Iterable接口,那么Iterable接口有什么用呢,打开源码,我们看到接口中有3个方法
Iterable
❝Iterator():返回元素类型为E的迭代器
forEach(Consumer<? super T> action):对内部元素进行遍历,并对元素进行指定的操作
spliterator():创建并返回一个可分割的迭代器
❞
//返回元素类型为E的迭代器
Iterator<T> iterator();
//对内部元素进行遍历,并对元素进行指定的操作
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
//创建并返回一个可分割的迭代器
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
对于Iterable接口中的Iterator()方法,我们应该不会陌生吧,因为我们在元素遍历的时候经常用到,我们重新回顾下iterator内的方法
iterator
❝hasNext():检查序列中是否还有元素
next():获得序列中的下一个元素
remove():将迭代器返回的元素删除
❞
public class TestIterator {
public static void main(String[] args){
Set<String> names=new HashSet<String>() ;
names.add("Simon");
names.add("Eric");
names.add("Kevin");
names.add("Edie");
Iterator<String> iterator=names.iterator();
while (iterator.hasNext()){
String name=iterator.next();
System.out.println(name);
}
}
}
我们以Collection的子类HashSet为例编写了测试,可以看出「Iterator就是在遍历集合中的元素,实际上,集合中的任意子类都可以使用Iterator」。
下面,我们学习下Collection中常用的方法
Collection接口中的方法
❝add(E e):添加一个元素
clear():清空集合中的所有元素
remove(Object o):移除集合中的指定元素
contains(Object o):检查集合中是否包含指定的元素
isEmpty():判断集合是否为空
size():判断集合中的元素个数
toArray():把集合中的元素存储到数组中
iterator():返回一个Iterator接口实现类的对象,进而实现集合的遍历
equals(Object o):判断与指定的元素(值)是否相等
❞
//判断集合中的元素个数
int size();
//检查集合中是否包含指定的元素
boolean contains(Object o);
//返回一个Iterator接口实现类的对象,进而实现集合的遍历
Iterator<E> iterator();
//把集合中的元素存储到数组中
Object[] toArray();
//添加一个元素
boolean add(E e);
//移除集合中的指定元素
boolean remove(Object o)
//清空集合中的所有元素
void clear();
//判断与指定的元素(值)是否相等
boolean equals(Object o);
接下来,我们主要来学习下Collection的子接口,「在这一部分,我们只介绍这些子接口的特点和方法,具体的实现类源码分析及应用会在以后的文章中开设具体的专题」。
2、List
List的做大特点是「集合内的元素的存储顺序和取出顺序一致,元素可重复。」
首先,我们先看List中的方法,打开List接口中的源码,我们发现它在原有的方法上多了如下几个方法
❝get(int index):返回list集合中指定的索引位置的元素
set(int index,E element):在索引index位置的元素更改为element元素
listIterator():返回次列表元素的列表迭代器
listIterator(int index):从指定位置开始,返回此列表元素的的列表迭代器
subList(int fromIndex,int toIndex):返回索引fromIndex到toIndex的元素集合
❞
E get(int index);
E set(int index, E element);
ListIterator<E> listIterator();
ListIterator<E> listIterator(int index);
List<E> subList(int fromIndex, int toIndex);
List接口主要有两个实现类ArrayList、LinkedList和Vector
共同点
❝都实现了Clonable接口,支持克隆
都实现了Serializable,支持序列化
❞
不同点
❝ArrayList和LinkedList是线程不安全的,Vector是线程安全的
ArrayList和Vector的底层数据结构是数组,LinkedList的底层数据结构是链表
❞
3、Set
Set集合继承于Collection接口,「不允许出现重复的元素」,是一个无序的集合。
首先,我们打开源码查看Set中的方法发现Set中的方法基本上Collection方法一致,如下图
Set的实现类主要有HashSet和TreeSet
「HashSet和TreeSet的区别」
TreeSet
❝TreeSet的底层数据结构是二叉树实现的,它可以保证集合内的元素处于一种有序的状态,不允许放入null值,判断两个对象是否相等是通过equals方法或者CompareTo方法比较的
❞
HashSet
❝底层的数据结构采用哈希表实现的,它要求放入的对象必须实现hashCode方法,以hashCode标识码来确定唯一的元素,允许放入null值,集合内元素的属于是无序的。
❞
看了这篇文章,你是否「博学」了
「扫码关注我」,每天博学一点点。