Java 集合学习笔记:Collection
Java 集合学习笔记:Collection
- UML
- 简介
- 方法和说明
- JDK8 新增 `default` 方法
- AbstractCollection
- isEmpty
- contains(Object o)
- toArray
- toArray()
- toArray(T[] a)
- add(E e)
- remove(Object o)
- containsAll(Collection> c)
- addAll(Collection extends E> c)
- removeAll(Collection> c)
- retainAll(Collection> c)
- clear()
- toString()
- 参考资料
UML

简介
Collection 表示包含了一组元素的对象,它定义了一系列用来折腾这些元素的方法。给徒子徒孙们立好了规矩。
通常不直接实现这个接口,而是实现它的两个徒弟 List、Set。
除非你要定义的是一个包含重复元素的无序 collection 。
方法和说明
| 限定符和类型 | 方法和说明 |
|---|---|
boolean | add(E e)确保此 collection 包含指定的元素(可选操作)。 |
boolean | addAll(Collection extends E> c)将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。 |
void | clear()移除此 collection 中的所有元素(可选操作)。 |
boolean | contains(Object o)如果此 collection 包含指定的元素,则返回 true。 |
boolean | containsAll(Collection> c)如果此 collection 包含指定 collection 中的所有元素,则返回 true。 |
boolean | equals(Object o)比较此 collection 与指定对象是否相等。 |
int | hashCode()返回此 collection 的哈希码值。 |
boolean | isEmpty()如果此 collection 不包含元素,则返回 true。 |
Iterator | iterator()返回在此 collection 的元素上进行迭代的迭代器。 |
boolean | remove(Object o)从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。 |
boolean | removeAll(Collection> c)移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。 |
boolean | retainAll(Collection> c)仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。 |
int | size()返回此 collection 中的元素数。 |
Object[] | toArray()返回包含此 collection 中所有元素的数组。 |
| toArray(T[] a)返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。 |
JDK8 新增 default 方法
| 限定符和类型 | 方法和说明 |
|---|---|
| default boolean | boolean removeIf(Predicate super E> filter) 删除此集合中满足给定谓词的所有元素。遍历中删除元素的求星。 |
| default Stream | Stream 返回以此集合为源的顺序流。 |
| default Stream | Stream 返回以此集合为源的可能并行的流。 |
| default Spliterator | Spliterator 在此集合中的元素上创建可拆分器迭代器。 |
AbstractCollection
抽象类 AbstractCollection 实现了一部分 Collection
isEmpty
因为此时还不知道底层实现类会使用什么数据结构,所以这里的size()是抽象的,留给子类去实现。
public boolean isEmpty() {return size() == 0;}
contains(Object o)
- 取迭代器,然后遍历所有元素,逐个判断如果发现与
给定元素相等的,就返回true 给定元素如果为null使用==判断是否相等,否则使用equals。
public boolean contains(Object o) {Iterator<E> it = iterator();if (o==null) {while (it.hasNext())if (it.next()==null)return true;} else {while (it.hasNext())if (o.equals(it.next()))return true;}return false;}
toArray
toArray()
返回包含此 collection 中所有元素的数组。如果 collection 对其迭代器返回的元素顺序做出了某些保证,那么此方法必须以相同的顺序返回这些元素。
返回的数组将是“安全的”,因为此 collection 并不引用返回的数组。(换句话说,即使 collection 底层实现就是数组,此方法也必须分配一个新的数组)。因此,调用者可以随意修改返回的数组。
此方法充当了基于Array API 与 基于collection API 之间的桥梁。
此实现返回一个数组,它包含此 collection 的迭代器返回的所有元素,这些元素的排列顺序与数组的连续元素存储顺序相同,都是从index 0 开始。返回数组的长度等于迭代器返回的元素数,即使此 collection 的大小发生更改也是如此,这种情况可能发生在 collection 允许在迭代期间进行并发修改的时候。size 方法只是作为一个优化提示被调用;即使迭代器返回不同的元素数,也会返回正确的结果。
此方法等效于:
Listlist = new ArrayList (size());
for (E e : this)
list.add(e);
return list.toArray();
- 以当前集合
size创建数组r。(后续会多退少补) - 遍历数组
r,每次从迭代器it中取一个元素,填充到数组r中。
2.1. 如果迭代器 < 数组迭代器到头后,将数组r复制一份,返回新数组。
2.2. 否则如果:数组r遍历完,迭代器也正好取完,则返回数组r。
2.3. 否则如果:数组r遍历完,迭代器还有元素,则调用finishToArray扩容数组r继续填充。
public Object[] toArray() {// 暂时用集合 size 创建数组。多了少了后面会处理的。Object[] r = new Object[size()];// 获取迭代器Iterator<E> it = iterator();// 循环数组 r 的长度。每次从迭代器 it 中返回一个结果填进数组 r// 如果填充到一半,迭代器已经完了,数组还没填满。// 则直接将数组 r 内容复制到【新数组】并返回。for (int i = 0; i < r.length; i++) {if (! it.hasNext()) // 元素比预期的少(迭代器到头了,数组还没填满)return Arrays.copyOf(r, i);r[i] = it.next();}// 如果数组 r 填满了,迭代器还有内容 ,则调用 finishToArray 继续处理。return it.hasNext() ? finishToArray(r, it) : r;}private static <T> T[] finishToArray(T[] r, Iterator<?> it) {// 取数组后的长度。(也是填充新元素的索引的位置)int i = r.length;// 迭代器继续遍历while (it.hasNext()) {// 取数组 r 当前长度为:容积(下面有扩容操作,所以这里每次都要获取更新)int cap = r.length;// 判断数组中【元素个数 i】与【容积 cap】如果相等,说明没空间了,就扩容数组 r。// 第一次执行到这,肯定是相等的。但数组扩容后,下一次再到这里【元素个数 i】就小于【容积 cap】了。// 每次向数组填充数据【元素个数 i】就+1,一直循环到下一次 i == cap 再次触发扩容。if (i == cap) {// 新容积 = 容积 + (容积 / 2 ) + 1int newCap = cap + (cap >> 1) + 1;// 对于溢出情况的处理if (newCap - MAX_ARRAY_SIZE > 0){ newCap = hugeCapacity(cap + 1); }// 复制数组 r 内容,并扩容到原 r 的 1.5 倍。r = Arrays.copyOf(r, newCap);}// 迭代器中取出元素,填充到数组 r 的索引 ir[i++] = (T)it.next();}// 去掉自动扩容多出来的位置。即:复制数组 r 第 0 到 i 的元素到新数组并返回。return (i == r.length) ? r : Arrays.copyOf(r, i);}// 容器尺寸过小,报错,过大就返回最大值。private static int hugeCapacity(int minCapacity) {if (minCapacity < 0)throw new OutOfMemoryError("Required array size too large");return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;}
toArray(T[] a)
可以看作是 toArray() 的升级版,用于指定返回数组的元素类。
- 返回数组的类型,与给定的数组
a一样。 - 如果我们给的数组
a尺寸够用,则直接向a中填充数据。 - 所以我们可以估计好数组大小,创建
a时直接指定大小,能省去扩容的消耗。
public <T> T[] toArray(T[] a) {// 取当前 collection 大小,作为参考值。int size = size();// 如果给定的数组 a 够,就直接用 a, 否则创建一个新数组 r(类型为 T)接收数据。T[] r = a.length >= size ? a :(T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);Iterator<E> it = iterator();for (int i = 0; i < r.length; i++) {// 如果迭代器已经到头了。if (! it.hasNext()) { // fewer elements than expected// 使用的就是给定数组 a ,将当前索引位置都设为 nullif (a == r) {r[i] = null; // null-terminate// 如果数组 a 长度小于已填充的元素个数 ,复制 r 到新数组并返回} else if (a.length < i) {return Arrays.copyOf(r, i);// 如果给定的数组 a 够大,将 r 中数据复制到 a 并返回,末尾空位都填充 null} else {System.arraycopy(r, 0, a, 0, i);if (a.length > i) {a[i] = null;}}return a;}// 从迭代器取出元素填进数组 rr[i] = (T)it.next();}// 如果数组填满,还没放完,扩容数组,继续填充。同 toArray()return it.hasNext() ? finishToArray(r, it) : r;}
add(E e)
实现了个寂寞。直接抛锅不支持的操作异常。
public boolean add(E e) {throw new UnsupportedOperationException();}
remove(Object o)
- 获取迭代器,遍历所有元素。
- 目标元素 o 为 null 时使用
==判断,否则使用equals。 - 删除操作,调用迭代器的
remove()实现。
public boolean remove(Object o) {Iterator<E> it = iterator();if (o==null) {while (it.hasNext()) {if (it.next()==null) {it.remove();return true;}}} else {while (it.hasNext()) {if (o.equals(it.next())) {it.remove();return true;}}}return false;}
containsAll(Collection> c)
遍历给定集合 c 的每个元素,判断它是否包含在当前集合 this 中。
只要 c 中有一个元素,不被 this 包含,就返回 false。
否则 c 中每个元素在当前集合中都存在,表示当前集合完全包含给定集合 c
public boolean containsAll(Collection<?> c) {for (Object e : c)if (!contains(e))return false;return true;}
addAll(Collection extends E> c)
- 遍历给定集合
c逐个向当前this集合中添加。 - 开头申明了一个
modified标记编辑状态。只要for中的add操作成功一次,就更新为true。
public boolean addAll(Collection<? extends E> c) {boolean modified = false;for (E e : c)if (add(e))modified = true;return modified;}
removeAll(Collection> c)
- 如果给定集合
c为null抛锅。 - 申明一个
modified标记编辑状态。只要while中的remove操作成功一次,就更新为true。 - 删除操作,底层通过当前集合的迭代器实现。
- 只要给定集合
c包含迭代器next()返回的对象,则执行remove操作。
public boolean removeAll(Collection<?> c) {Objects.requireNonNull(c);boolean modified = false;Iterator<?> it = iterator();while (it.hasNext()) {if (c.contains(it.next())) {it.remove();modified = true;}}return modified;}
retainAll(Collection> c)
与 removeAll 相反,c 不包含 next() 返回的对象就删除。(即:包含就保留)
public boolean retainAll(Collection<?> c) {Objects.requireNonNull(c);boolean modified = false;Iterator<E> it = iterator();while (it.hasNext()) {if (!c.contains(it.next())) {it.remove();modified = true;}}return modified;}
clear()
获取迭代器,逐个删除。
public void clear() {Iterator<E> it = iterator();while (it.hasNext()) {it.next();it.remove();}}
toString()
- 获取迭代器,判断如果没内容就返回字符串
[]。 - 创建
StringBuilder将每个元素添加进去。直到所有元素添加完sb.toString();
public String toString() {Iterator<E> it = iterator();if (! it.hasNext())return "[]";StringBuilder sb = new StringBuilder();sb.append('[');for (;;) {E e = it.next();sb.append(e == this ? "(this Collection)" : e);if (! it.hasNext())return sb.append(']').toString();sb.append(',').append(' ');}}
参考资料
Collection 单列集合(单值)
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
