Java的集合 1
首先要知道集合是什么,基于现代汉语词典给定的定义:
- 许多分散的人或物聚集在一起
- 数学上指若干具有共同属性的事物的总体
- 使集合
计算机程序是对现实社会或流程的模拟体现+根据上面现代汉语词典的定义,因此,在Java中的集合就得满足一定的要求:
- 聚集一定的对象或数据
- 能够有一定的方式去处理这些聚集起来的对象或数据
一、Java集合图
1.1 整体图
上图是整个JavaSE jdk1.8的所有与集合相关的类,当然我们不会研究那么多
1.2 重点部分图
Java中的集合分为可迭代和不可迭代两种:
Collection接口、子接口及其实现 和 Map接口、子接口及其实现
二、可迭代的集合
2.1 Iterable接口
整体方法图:
方法:
能够迭代集合元素的迭代器
Iterator<T> iterator();
返回此集合中元素的迭代器。对于元素返回的顺序没有保证(除非这个集合是某个提供保证的类的实例)。
函数式编程,迭代每个元素
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
转成Spliterator
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
在此Iterable所描述的元素上创建一个Spliterator。
2.2 Collection接口
整体方法图
方法:
在上一级的方法基础上添加如下方法:
集合大小
int size();
返回此集合中的元素数。如果此集合包含超过Integer.MAX_VALUE
个元素返回 Integer.MAX_VALUE
判空
boolean isEmpty();
如果此集合不包含元素,则返回true。
包含不包含某个对象
boolean contains(Object o);
如果此集合包含指定的元素,则返回true。当且仅当该集合包含至少一个元素e,且满足(onull ?enull : o.equals(e))。
转成普通的数组
Object[] toArray();
返回一个包含此集合中所有元素的数组。如果该集合对其迭代器返回元素的顺序有任何保证,则该方法必须以相同的顺序返回元素。
返回的数组将是“安全的”,因为此集合不会维护对它的任何引用。(换句话说,这个方法必须分配一个新的数组,即使这个集合是由数组支持的)。因此,调用者可以自由地修改返回的数组。
该方法充当了基于数组和基于集合的api之间的桥梁。
转化成普通数组
<T> T[] toArray(T[] a);
返回一个包含此集合中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。如果集合符合指定的数组,则在其中返回。否则,将使用指定数组的运行时类型和此集合的大小分配新数组。
如果这个集合适合指定的数组,并且有空闲空间(即,数组的元素比这个集合多),则紧跟在集合末尾的数组中的元素将被设置为空。(只有当调用者知道这个集合不包含任何空元素时,这在确定这个集合的长度时才有用。)
如果该集合对其迭代器返回元素的顺序有任何保证,则该方法必须以相同的顺序返回元素。
与toArray()方法一样,该方法充当了基于数组和基于集合的api之间的桥梁。此外,这种方法允许对输出数组的运行时类型进行精确控制,并且在某些情况下,可以用于节省分配成本。
假设x是一个已知只包含字符串的集合。以下代码可用于将集合转储到新分配的String数组中:
String[] y = x.toArray(new String[0]);
注意,toArray(new Object[0])在功能上与toArray()相同。
添加元素
boolean add(E e);
确保此集合包含指定的元素(可选操作)。如果此集合因调用而改变,则返回true。(如果该集合不允许重复且已经包含指定元素,则返回false。)
支持此操作的集合可以对可添加到此集合的元素设置限制。特别是,一些集合将拒绝添加空元素,而其他集合将对可能添加的元素类型施加限制。集合类应该在其文档中清楚地指定可以添加的元素的任何限制。
如果一个集合拒绝添加某个特定元素的原因不是因为它已经包含了该元素,那么它必须抛出异常(而不是返回false)。这将保留集合在此调用返回后始终包含指定元素的不变式。
删除元素
boolean remove(Object o);
如果存在,则从此集合中删除指定元素的单个实例(可选操作)。确切的说,删除一个元素e,使(o==null ?E ==null: o.equals(E))
,如果这个集合包含一个或多个这样的元素。如果该集合包含指定的元素,则返回true(或者等效地,如果该集合因调用而改变)。
传入集合的所有元素在当前集合中是否都有
boolean containsAll(Collection<?> c);
如果此集合包含指定集合中的所有元素,则返回true。
把传入集合的所有元素添加到当前集合
boolean addAll(Collection<? extends E> c);
将指定集合中的所有元素添加到此集合(可选操作)。如果在操作进行时修改了指定的集合,则此操作的行为是未定义的。(这意味着如果指定的集合为此集合,且此集合非空,则此调用的行为是未定义的。)
传入集合和当前集合都存在的元素,在当前集合删除
boolean removeAll(Collection<?> c);
删除此集合中也包含在指定集合中的所有元素(可选操作)。此调用返回后,此集合将不包含与指定集合相同的元素。
通过过滤器删除指定元素
default boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
删除集合中满足给定谓词的所有元素。在迭代期间或由谓词抛出的错误或运行时异常被传递给调用者。
保留传入集合与当前集合的相同元素
boolean retainAll(Collection<?> c);
仅保留此集合中包含在指定集合中的元素(可选操作)。换句话说,从该集合中删除未包含在指定集合中的所有元素。
清空
void clear();
从此集合中移除所有元素(可选操作)。该方法返回后,集合将为空。
重写equals
boolean equals(Object o);
将指定对象与此集合进行比较以确定是否相等。
虽然Collection接口没有向Object.equals
的一般情况下添加任何规定,但是“直接”实现Collection接口(换句话说,创建一个Collection但不是Set或List的类)的程序员在选择重写Object.equals
时必须非常小心。没有必要这样做,最简单的做法是依赖Object的实现,但是实现者可能希望实现一个“值比较”来代替默认的“引用比较”。(List和Set接口要求这样的值比较。)
对象的总合同。Equals方法声明Equals必须是对称的(换句话说,当且仅当b等于(a)时,a等于(b))。合同清单。=和Set。Equals表示列表只与其他列表相等,集合只与其他集合相等。因此,既不实现List接口也不实现Set接口的集合类的自定义equals方法在将该集合与任何列表或集进行比较时必须返回false。(按照同样的逻辑,不可能编写一个正确实现Set和List接口的类。)
重写hashCode
int hashCode();
返回此集合的哈希码值。而Collection接口没有为Object的一般契约添加任何规定。hashCode方法,程序员应该注意任何重写Object. hashCode方法的类。equals方法也必须重写Object。hashCode方法,以满足对象的一般契约。hashCode方法。特别地,c1.equals(c2)
意味着c1.hashCode()==c2. hashcode()
。
转换成Stream
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
转换成ParallelStream
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
2.3 List接口
整体方法图
方法:
除了继承的Collection接口和Iterable接口的方法之外
从指定位置添加集合
boolean addAll(int index, Collection<? extends E> c);
将指定集合中的所有元素插入此列表的指定位置(可选操作)。将当前位于该位置的元素(如果有的话)和所有后续元素向右移动(增加它们的下标)。新元素将按照指定集合的迭代器返回的顺序出现在此列表中。如果在操作进行时修改了指定的集合,则此操作的行为是未定义的。(注意,如果指定的集合是这个列表,并且它是非空的,就会发生这种情况。)
按照指定操作替换元素
default void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final ListIterator<E> li = this.listIterator();
while (li.hasNext()) {
li.set(operator.apply(li.next()));
}
}
将此列表中的每个元素替换为对该元素应用运算符的结果。操作符抛出的错误或运行时异常被传递给调用方。
传入Comparator,进行排序
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
根据指定比较器发出的顺序对此列表进行排序。
这个列表中的所有元素都必须与指定的比较器相比较(即c)。比较(e1,e2)不能在列表中抛出任意元素e1和e2的ClassCastException。
如果指定的比较器是空的,那么这个列表中的所有元素都必须实现可比的接口,应该使用元素的自然顺序。
这个列表必须修改,但不需要调整。
指定位置的元素
E get(int index);
返回列表中指定位置的元素。
指定位置元素替换
E set(int index, E element);
用指定的元素(可选操作)替换该列表中指定位置的元素。
指定位置添加元素
void add(int index, E element);
将指定元素插入此列表中的指定位置(可选操作)。将当前位于该位置的元素(如果有的话)和所有后续元素向右移动(向它们的下标添加1)。
删除元素
E remove(int index);
在此列表(可选操作)中删除指定位置的元素。将任何后续元素移到左边(从它们的索引中减去一个元素)。返回从列表中删除的元素。
查找元素下标 (最先)
int indexOf(Object o);
返回指定元素在此列表中第一次出现的索引,如果该列表不包含该元素,则返回-1。更正式地说,返回最低下标i,使(o==null ? get(i)==null : o.equals(get(i)))
,如果没有这样的下标,则为-1。
查找元素下标(最后)
int lastIndexOf(Object o);
返回这个列表中指定元素的最后一次的索引,或者如果这个列表不包含元素,则返回-1。更正式地说,返回最高下标i,使(o==null ? get(i)==null : o.equals(get(i)))
,如果没有这样的下标,则为-1。
获得一个list迭代器
ListIterator<E> listIterator();
在这个列表中返回一个列表迭代器(适当的顺序)。
从指定位置开始返回一个list迭代器
ListIterator<E> listIterator(int index);
在列表中返回一个列表迭代器,从列表中的指定位置开始。指定的索引表示第一个元素,它将由初始调用返回。初始调用之前将返回指定索引- 1的元素。
子列表截取
List<E> subList(int fromIndex, int toIndex);
返回该列表中指定的fromIndex(包含)和toIndex(不包含)之间部分的视图。(如果fromIndex和toIndex相等,返回的列表为空。)返回的列表由该列表支持,因此返回列表中的非结构性更改会反映在该列表中,反之亦然。返回的列表支持该列表支持的所有可选列表操作。
这种方法消除了显式范围操作的需要(通常存在于数组的那种操作)。任何需要一个列表的操作都可以通过传递一个subblist视图而不是整个列表来用作范围操作。例如,下面的习惯用法从列表中移除一系列元素:
list.subList(from, to).clear();
可以为indexOf和lastIndexOf构造类似的习惯用法,Collections类中的所有算法都可以应用于子列表。
如果支持列表(即此列表)在结构上以任何方式修改,而不是通过返回的列表,则此方法返回的列表的语义将变为未定义。(结构修改是指那些改变列表大小的修改,或者以某种方式扰乱列表,使正在进行的迭代可能产生不正确的结果。)
定的fromIndex(包含)和toIndex(不包含)之间部分的视图。(如果fromIndex和toIndex相等,返回的列表为空。)返回的列表由该列表支持,因此返回列表中的非结构性更改会反映在该列表中,反之亦然。返回的列表支持该列表支持的所有可选列表操作。
这种方法消除了显式范围操作的需要(通常存在于数组的那种操作)。任何需要一个列表的操作都可以通过传递一个subblist视图而不是整个列表来用作范围操作。例如,下面的习惯用法从列表中移除一系列元素:
list.subList(from, to).clear();
可以为indexOf和lastIndexOf构造类似的习惯用法,Collections类中的所有算法都可以应用于子列表。
如果支持列表(即此列表)在结构上以任何方式修改,而不是通过返回的列表,则此方法返回的列表的语义将变为未定义。(结构修改是指那些改变列表大小的修改,或者以某种方式扰乱列表,使正在进行的迭代可能产生不正确的结果。)