# Collection
容器由来
对象数组:数组可以存储基本数据类型和引用类型,存储引用类型的数组就叫对象数组
容器(container)
由来 Java-->面向对象-->操作很多对象-->存储-->容器
- 容器与数组的区别
- 长度 数组固定,容器(集合)可变
- 存储类型 数组可以是基本类型和引用类型,容器(集合)只能是引用类型
- 元素类型 数组只能存储同一类型,容器(集合)可以存储不同类型(一般也存储同一种类型)
- 方法 数组方法有限,增删改非常不便,效率也不高;集合就不同了,可选择性多
- 数据结构 数组元素有序可重复;集合可选择多
- 容器与数组的区别
# Collection(java.util)
# 简介
Collection是所有单列集合的父接口,在Collection中定义了单列集合List、Set和Queue通用的一些方法,这些方法可用于操作所有的单列集合。
由于其重写了toString()方法,所以可以直接打印其内容。这点与数组不同,数组需要借助Arrays工具类

# 常用方法
注意
Collection如下方法底层会调用equals()判断,所以操作自定义类型时需要重写equals()
- 添加
boolean add(E e):添加该对象到下一个索引,当成一个元素boolean addAll(Collection c):复制容器中其每一个元素,每个单独添加
- 删除
void clear():删除集合中所有元素,但集合还存在boolean remove(Object o):区别 List 中的boolean removeAll(Collection c):差集关系default boolean removeIf(Predicate<? super E> filter):根据条件删除
- 判断
boolean isEmpty()boolean contains(Object o):boolean containsAll(Collection<?> c):子集关系boolean equals(Object o):(根据实际对象可能根据元素顺序依次)对比每个元素int hashCode()
- 交集
boolean retainAll(Collection<?> c):交集
- 获取容量
int size()
- 返回迭代器,
Collection特有Iterator iterator()
- 集合转数组
Object[] toArray()
- Stream 流
# Iterable(java.lang)
Collection接口继承了java.lang.Iterable接口,该接口有一个iterator()方法,返回一个实现了Iterator接口的对象。
# Iterator(java.util)
Iterator对象称为迭代器(设计模式的一种),主要用于遍历Collection集合中的元素。- GOF给迭代器模式的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。迭代器模式,就是为容器而生。类似于“公交车上的售票员”、“火车上的乘务员”、“空姐”。——检票
Iterator仅用于遍历集合,Iterator本身并不提供承装对象的能力。如果需要创建Iterator对象,则必须有一个被迭代的集合。集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。
常用方法:
Iterator<E> iterator(): 获取Collection对应的迭代器,用来遍历集合中的元素的。这个接口的泛型跟着所属集合走,集合是什么泛型,迭代器就是什么泛型。每次调用都会得到一个全新的迭代器对象。boolean hasNext():如果容器中还有元素可以迭代,则返回 true。E next():指针下移,并返回迭代的元素。default void remove():删除集合的元素。但是是遍历过程中通过迭代器对象的remove方法,不是集合对象的remove方法。如果还未调用next()或在上一次调用next()方法之后已经调用了remove方法,再调用remove都会报IllegalStateException。Iterator<String> iterator = c.iterator(); while (iterator.hasNext()) { // iterator.remove();// 错误 String next = iterator.next(); if ("123".equals(next)) { iterator.remove(); } // iterator.remove();// 错误 }
迭代器执行原理如下:

在调用
it.next()方法之前必须要调用it.hasNext()进行检测。若不调用,且下一条记录无效,会抛出NoSuchElementException异常。Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素。在调用Iterator的next()方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next()方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次~。依此类推,直到hasNext()方法返回false,表示到达了集合的末尾,终止对元素的遍历。
# for each循环
增强for循环(也称foreach循环)是JDK1.5以后出来的一个高级for循环,专门用来遍历
Array和Collection。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,尽量不要对Collection中的元素进行增删操作。Collection<E> extends Iterable<E>,(所有Collection)实现此接口允许对象成为“foreach”语句目标。ArrayList<String> arraylist = new ArrayList<>(); for(String s:arraylist){ System.out.println(s); }
# 并发修改异常
ConcurrentModificationException现象:迭代器遍历集合,集合修改集合元素原因:迭代器依赖于集合,而集合的改变导致迭代器预期的迭代次数发生改变
解决:
迭代器遍历,并利用
Iterator的remove方法集合遍历,集合修改(利用
get()和size()),增加元素在集合末尾删除元素时并跟上break语句