java8 Collection新特性用法示例源码分析
新特性
Java 8在java.util.Collection
接口中引入的新方法如下:
removeIf(Predicate<? super E> filter)
:根据给定的条件(Predicate)删除集合中满足条件的元素。stream()
:返回一个顺序流,可用于对集合进行流式操作。parallelStream()
:返回一个并行流,可同时对集合中的元素进行并行操作。spliterator()
:创建一个Spliterator,用于描述集合中的元素。
这些新方法为集合的操作提供了更灵活、简洁和高效的方式。通过使用Lambda表达式和流式操作,可以以一种声明性的方式对集合进行处理,减少了样板代码的编写,并且使得代码更易读和维护。新增的方法也提供了更多的功能和扩展性,方便了集合的操作和处理。
用法示例
Java 8在java.util.Collection
接口中引入的新方法的签名、用法和代码示例如下:
-
removeIf(Predicate<? super E> filter)
- 签名:
boolean removeIf(Predicate<? super E> filter)
- 用法:根据给定的条件删除集合中满足条件的元素。
- 代码示例:
List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)); // 使用removeIf方法删除奇数 numbers.removeIf(n -> n % 2 != 0); System.out.println(numbers); // 输出: [2, 4]
- 签名:
-
stream()
- 签名:
Stream<E> stream()
- 用法:返回一个顺序流,可用于对集合进行流式操作。
- 代码示例:
List<String> fruits = Arrays.asList("apple", "banana", "orange"); // 使用stream方法过滤长度大于5的水果,并将结果转换为大写后打印出来 fruits.stream() .filter(fruit -> fruit.length() > 5) .map(String::toUpperCase) .forEach(System.out::println);
- 签名:
-
parallelStream()
- 签名:
Stream<E> parallelStream()
- 用法:返回一个并行流,可同时对集合中的元素进行并行操作。
- 代码示例:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); // 使用parallelStream方法计算集合中元素的平方和 int sum = numbers.parallelStream() .mapToInt(n -> n * n) .sum(); System.out.println(sum); // 输出: 55
- 签名:
-
spliterator()
- 签名:
Spliterator<E> spliterator()
- 用法:创建一个Spliterator,用于描述集合中的元素。
- 代码示例:
List<String> colors = Arrays.asList("red", "green", "blue"); // 使用spliterator方法遍历集合,并将每个元素转换为大写后打印出来 Spliterator<String> spliterator = colors.spliterator(); spliterator.forEachRemaining(color -> System.out.println(color.toUpperCase()));
- 签名:
这些新方法为集合的操作提供了更加灵活、简洁和高效的方式。通过使用Lambda表达式和流式操作,可以以一种声明性的方式对集合进行处理,减少了样板代码的编写,并且使得代码更易读和维护。同时,新增的方法也提供了更多的功能和扩展性,方便了集合的操作和处理。
中文源码
package java.util;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/**
* 集合层次结构中的根接口。集合表示一组对象,称为其元素。某些集合允许重复的元素,而其他集合则不允许。有些是有序的,而其他则无序的。
* JDK不提供此接口的任何“直接”实现:它提供了更具体的子接口(如Set和List)的实现。此接口通常用于传递集合并在其中执行操作时需要最大的通用性。
*
* <p>应该直接实现此接口的<i>包或多集</i>(可能包含重复元素的无序集合)。
*
* <p>所有通用Collection实现类(通常通过其子接口间接实现Collection)应提供两个“标准”构造函数:
* 一个无参构造函数,创建一个空集合;以及一个带有单个类型为Collection的参数的构造函数,
* 创建一个与其参数具有相同元素的新集合。事实上,后一个构造函数允许用户复制任何集合,生成所需实现类型的等效集合。
* 没有办法强制执行此约定(因为接口不能包含构造函数),但Java平台库中的所有通用Collection实现都符合该约定。
*
* <p>在进行修改的方法中,如果集合不支持操作,则指定抛出UnsupportedOperationException。如果是这种情况,
* 这些方法可以(但不是必须)在调用对集合没有影响时抛出UnsupportedOperationException异常。
* 例如,在不可修改的集合上调用addAll(Collection)方法可能会(但并不一定)抛出异常,如果要添加的集合为空。
*
* <p><a name="optional-restrictions">
* 一些集合实现对其可能包含的元素有限制。</a>例如,某些实现禁止空元素,而其他实现对其元素的类型有限制。
* 尝试添加不合格的元素会引发未检查的异常,通常为NullPointerException或ClassCastException。
* 尝试查询不合格元素的存在可能会引发异常,或者可能只返回false;
* 某些实现将呈现前一种行为,而其他实现将呈现后一种行为。更一般地说,尝试对不合格元素执行操作,
* 如果完成不会导致将不合格元素插入到集合中,则可能引发异常或成功,具体取决于实现的选择。
* 此类异常在本接口的规范中标为“可选”。
*
* <p>每个集合都可以确定其自己的同步策略。在没有实现提供更强保证的情况下,
* 在另一个线程对集合进行变异的方法调用可能导致不确定的行为;这包括直接调用、将集合传递给可能执行调用的方法以及使用现有迭代器来检查集合。
*
* <p>Collections Framework接口中的许多方法是根据equals方法定义的。
* 例如,对于contains(Object o)方法的规范说:“当且仅当此集合包含至少一个元素e使得(o==null ? e==null : o.equals(e))”时返回true。
* 不应将此规范误解为意味着调用Collection.contains具有非空参数o将导致为任何元素e调用o.equals(e)。
* 实现可以选择避免调用equals方法,例如,通过首先比较两个元素的哈希码。(Object.hashCode()规范确保具有不相等哈希码的两个对象不相等。)
* 更一般地说,在各种Collections Framework接口的实现中,可以根据底层Object方法的指定行为来利用底层Object方法的指定行为,只要实现者认为适当即可。
*
* <p>某些执行递归遍历集合的集合操作可能会因集合直接或间接地包含自身而失败。
* 这包括clone()、equals()、hashCode()和toString()方法。实现可以选择处理自我引用场景,但大多数当前实现不会这样做。
*
* <p>此接口是<a href="{@docRoot}/../technotes/guides/collections/index.html">
* Java Collections Framework</a>的成员。
*
* @implSpec
* 默认方法实现(无论是继承的还是其他方式)不适用任何同步协议。
* 如果集合实现具有特定的同步协议,则必须覆盖默认实现以应用该协议。
*
* @param <E> 集合中的元素类型
*
* @author Josh Bloch
* @author Neal Gafter
* @see Set
* @see List
* @see Map
* @see SortedSet
* @see SortedMap
* @see HashSet
* @see TreeSet
* @see ArrayList
* @see LinkedList
* @see Vector
* @see Collections
* @see Arrays
* @see AbstractCollection
* @since 1.2
*/
public interface Collection<E> extends Iterable<E> {
// 查询操作
/**
* 返回集合中的元素数量。如果此集合包含的元素超过Integer.MAX_VALUE个,则返回Integer.MAX_VALUE。
*
* @return 集合中的元素数量
*/
int size();
/**
* 如果此集合不包含任何元素,则返回true。
*
* @return 如果此集合不包含任何元素,则返回true
*/
boolean isEmpty();
/**
* 如果此集合包含指定的元素,则返回true。更确切地讲,当且仅当此集合包含至少一个元素e使得
* (o==null ? e==null : o.equals(e))时返回true。
*
* @param o 要在此集合中测试其存在的元素
* @return 如果此集合包含指定的元素,则返回true
* @throws ClassCastException 如果指定元素的类与此集合不兼容
* (<a href="#optional-restrictions">可选</a>)
* @throws NullPointerException 如果指定的元素为null,且此集合不允许null元素
* (<a href="#optional-restrictions">可选</a>)
*/
boolean contains(Object o);
/**
* 返回在此集合中的元素上进行迭代的迭代器。对元素返回的顺序没有任何保证(除非此集合是某个提供保证的类的实例)。
*
* @return 在此集合中的元素上进行迭代的Iterator
*/
Iterator<E> iterator();
/**
* 返回包含此集合中所有元素的数组。如果此集合对其元素的迭代器返回元素的顺序有任何保证,
* 则该方法必须以相同的顺序返回这些元素。
*
* <p>返回的数组将是“安全的”,因为此集合不保留对它的任何引用。
* (换句话说,即使此集合由数组支持,此方法也必须分配一个新的数组)。
* 因此,调用者可以自由地修改返回的数组。
*
* <p>此方法充当了基于数组和基于集合的API之间的桥梁。
*
* @return 包含此集合中所有元素的数组
*/
Object[] toArray();
/**
* 返回包含此集合中所有元素的数组;返回数组的运行时类型与指定数组的类型相同。
* 如果集合适合指定的数组,则在其中返回它。否则,将分配一个具有指定数组运行时类型和此集合大小的新数组。
*
* <p>如果此集合适合指定的数组并有剩余空间(即数组中的元素多于此集合的元素),
* 那么紧随此集合结束的那个元素设置为null。(仅当调用者知道此集合不包含任何null元素时,才能确定此长度)。
*
* <p>如果此集合对其元素的迭代器返回元素的顺序有任何保证,
* 则该方法必须以相同的顺序返回这些元素。
*
* <p>与{@link #toArray()}方法一样,此方法充当了基于数组和基于集合的API之间的桥梁。
* 此外,此方法允许对输出数组的运行时类型进行精确控制,并且在某些情况下,可以减少分配成本。
*
* <p>假设x是只包含字符串的集合。以下代码可用于将集合转储到新分配的String数组中:
*
* <pre>
* String[] y = x.toArray(new String[0]);
* </pre>
*
* 注意,toArray(new Object[0])在功能上等同于toArray()。
*
* @param <T> 包含集合的数组的运行时类型
* @param a 包含集合的元素的数组,如果它足够大;否则,将为此目的分配一个具有相同运行时类型的新数组。
* @return 包含此集合中所有元素的数组
* @throws ArrayStoreException 如果指定数组的运行时类型不是每个元素的运行时类型的超类型
* @throws NullPointerException 如果指定的数组为空
*/
<T> T[] toArray(T[] a);
// 修改操作
/**
* 确保此集合包含指定的元素(可选操作)。如果因为调用而更改了此集合,则返回true。
* (返回false表示此集合不允许重复,且已经包含指定的元素)<p>
*
* 支持此操作的集合可能对添加到该集合中的元素有所限制。
* 特别是,某些集合将拒绝添加null元素,而其他集合将对可添加的元素类型施加限制。
* 集合类应在其文档中清楚地说明可以添加哪些元素的限制。
*
* 如果集合因为任何原因(除了已经包含元素)而拒绝添加特定元素,
* 它<i>必须</i>抛出异常(而不是返回false)。这保留了不变式,即调用后此集合始终包含指定的元素。
*
* @param e 确保存在于此集合中的元素
* @return 如果由于调用而更改了此集合,则返回true
* @throws UnsupportedOperationException 如果此集合不支持add操作
* @throws ClassCastException 如果指定元素的类使其无法添加到此集合中
* @throws NullPointerException 如果指定的元素为空,并且此集合不允许空元素
* @throws IllegalArgumentException 如果元素的某些属性使其无法添加到此集合中
* @throws IllegalStateException 如果由于插入限制,此时无法添加元素
*/
boolean add(E e);
/**
* 从此集合中删除指定元素的单个实例(如果存在)(可选操作)。
* 更正式地说,如果此集合包含一个或多个这样的元素e,
* 则会删除一个元素e,使得(o==null ? e==null : o.equals(e))为true。
* 如果该集合包含指定的元素(或者等效地,如果此集合由于调用而更改),
* 则返回true。
*
* @param o 要从此集合中删除的元素(如果存在)
* @return 如果由于调用而更改了此集合,则返回true
* @throws ClassCastException 如果指定元素的类型与此集合不兼容
* (<a href="#optional-restrictions">可选</a>)
* @throws NullPointerException 如果指定元素为空,并且此集合不允许空元素
* (<a href="#optional-restrictions">可选</a>)
* @throws UnsupportedOperationException 如果此集合不支持remove操作
*/
boolean remove(Object o);
// 批量操作
/**
* 如果此集合包含指定集合中的所有元素,则返回true。
*
* @param c 包含在此集合中进行包含检查的集合
* @return 如果此集合包含指定集合中的所有元素,则返回true
* @throws ClassCastException 如果指定集合中的一个或多个元素的类型与此集合不兼容
* (<a href="#optional-restrictions">可选</a>)
* @throws NullPointerException 如果指定集合包含一个或多个null元素,并且此集合不支持null元素
* (<a href="#optional-restrictions">可选</a>);
* 或者指定集合为null。
* @see #contains(Object)
*/
boolean containsAll(Collection<?> c);
/**
* 将指定集合中的所有元素添加到此集合(可选操作)。
* 如果操作进行时修改了指定的集合(除非该集合是此集合并且它是非空的),
* 那么此操作的行为是未定义的。(这意味着,如果指定集合是此集合,并且此集合是非空的,
* 则此调用的行为是未定义的。)
*
* @param c 包含要添加到此集合的元素的集合
* @return 如果由于调用而更改了此集合,则返回true
* @throws UnsupportedOperationException 如果此集合不支持addAll操作
* @throws ClassCastException 如果指定集合的一个元素的类阻止将其添加到此集合中
* @throws NullPointerException 如果指定集合包含一个null元素,并且此集合不允许null元素,
* 或者指定集合为空
* @throws IllegalArgumentException 如果指定集合的一个元素的某些属性阻止将其添加到此集合中
* @throws IllegalStateException 如果由于插入限制,此时无法添加所有元素
* @see #add(Object)
*/
boolean addAll(Collection<? extends E> c);
/**
* 从此集合中删除与指定集合中包含的所有元素相同的元素(可选操作)。
* 在此调用返回后,此集合将不包含与指定集合中的任何元素相同的元素。
*
* @param c 包含要从此集合中删除的元素的集合
* @return 如果由于调用而更改了此集合,则返回true
* @throws UnsupportedOperationException 如果此集合不支持removeAll方法
* @throws ClassCastException 如果此集合的一个或多个元素的类型与指定集合不兼容
* (<a href="#optional-restrictions">可选</a>)
* @throws NullPointerException 如果此集合包含一个或多个null元素,并且指定集合不支持null元素
* (<a href="#optional-restrictions">可选</a>),
* 或者指定集合为null
* @see #remove(Object)
* @see #contains(Object)
*/
boolean removeAll(Collection<?> c);
/**
* 删除满足给定谓词的此集合的所有元素。迭代期间或谓词引发的错误或运行时异常将被传递给调用者。
*
* @implSpec
* 默认实现使用其{@link #iterator}遍历集合的所有元素。
* 使用{@link Iterator#remove()}删除每个匹配的元素。
* 如果集合的迭代器不支持删除操作,则在第一个匹配元素上抛出UnsupportedOperationException异常。
*
* @param filter 谓词,用于返回要删除的元素
* @return 如果删除了任何元素,则为true
* @throws NullPointerException 如果指定的过滤器为null
* @throws UnsupportedOperationException 如果无法从此集合中删除元素。
* 如果匹配元素无法删除或者一般不支持删除,实现可以抛出此异常。
* @since 1.8
*/
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;
}
/**
* 仅保留在此集合中包含在指定集合中的元素(可选操作)。
* 换句话说,从此集合中删除未包含在指定集合中的所有元素。
*
* @param c 包含在此集合中保留的元素的集合
* @return 如果由于调用而更改了此集合,则返回true
* @throws UnsupportedOperationException 如果此集合不支持retainAll操作
* @throws ClassCastException 如果此集合的一个或多个元素的类型与指定集合不兼容
* (<a href="#optional-restrictions">可选</a>)
* @throws NullPointerException 如果此集合包含一个或多个null元素,并且指定集合不支持null元素
* (<a href="#optional-restrictions">可选</a>),
* 或者指定集合为null
* @see #remove(Object)
* @see #contains(Object)
*/
boolean retainAll(Collection<?> c);
/**
* 从此集合中删除所有元素(可选操作)。此方法调用返回后,集合将为空。
*
* @throws UnsupportedOperationException 如果此集合不支持clear操作
*/
void clear();
// 比较和哈希
/**
* 将指定对象与此集合进行比较以实现相等性。 <p>
*
* 虽然Collection接口对Object.equals的一般契约没有添加任何规定,
* 但直接实现Collection接口的程序员(换句话说,创建一个是Collection但不是Set或List的类)
* 如果选择覆盖Object.equals,则必须小心。没有必要这样做,最简单的操作是依赖于Object的实现,
* 但是实现者可能希望在默认的“引用比较”之外实现“值比较”。
* (List和Set接口强制执行这样的值比较。)<p>
*
* Object.equals方法的通用契约规定equals必须是对称的(换句话说,a.equals(b)当且仅当b.equals(a))。
* List.equals和Set.equals的契约规定列表仅等于其他列表,并且集合仅等于其他集合。
* 因此,实现了既不是List也不是Set接口的集合类必须在与任何列表或集合进行比较时返回false。
* (基于同样的逻辑,不可能编写正确实现同时正确实现Set和List接口。)
*
* @param o 要与此集合进行比较的对象
* @return 如果指定对象等于此集合,则返回true
*
* @see Object#equals(Object)
* @see Set#equals(Object)
* @see List#equals(Object)
*/
boolean equals(Object o);
/**
* 返回此集合的哈希码值。虽然Collection接口对Object.hashCode方法的一般约定没有添加任何规定,
* 但是程序员应注意,任何覆盖Object.equals方法的类也必须覆盖Object.hashCode方法,
* 以便满足Object.hashCode方法的一般约定。特别是,c1.equals(c2)意味着c1.hashCode()==c2.hashCode()。
*
* @return 此集合的哈希码值
*
* @see Object#hashCode()
* @see Object#equals(Object)
*/
int hashCode();
/**
* 在此集合上创建一个Spliterator。
*
* 实现应该记录由spliterator报告的特征值。
* 如果spliterator报告{@link Spliterator#SIZED}并且该集合不包含任何元素,则不需要报告此类特征值。
*
* <p>默认实现应该被子类覆盖,以提供更高效的spliterator。
* 为了保持对{@link #stream()}和{@link #parallelStream()}方法预期的延迟行为,
* spliterators应该具有{@code IMMUTABLE}或{@code CONCURRENT}特征,
* 或者是<em><a href="Spliterator.html#binding">late-binding</a></em>的。
* 如果以上都不可行,那么重写的类应该描述spliterator绑定和结构干扰的文档策略,并且应该通过使用
* {@code Supplier}提供spliterator的stream()和parallelStream()方法来创建流,如下所示:
* <pre>{@code
* Stream<E> s = StreamSupport.stream(() -> spliterator(), spliteratorCharacteristics)
* }</pre>
* <p>这些要求确保由{@link #stream()}和{@link #parallelStream()}方法生成的流将反映集合的内容,
* 此内容将在初始化终端流操作时生效。
*
* @implSpec
* 默认实现从集合的{@code Iterator}创建一个<em><a href="Spliterator.html#binding">late-binding</a></em>的spliterator。
* spliterator继承集合的迭代器的fail-fast属性。
* <p>
* 创建的{@code Spliterator}报告{@link Spliterator#SIZED}。
*
* @implNote
* 创建的{@code Spliterator}还报告{@link Spliterator#SUBSIZED}。
*
* <p>如果spliterator不包含任何元素,则除了{@code SIZED}和{@code SUBSIZED}之外,额外的特征值的报告对客户端来说是无用的,
* 因为这些值对于控制、专门化或简化计算没有帮助。然而,这确实启用了空集合的共享使用
* 不可变和空Spliterator实例(请参阅{@link Spliterators#emptySpliterator()}),
* 并使客户端能够确定这样一个spliterator是否不包含任何元素。
*
* @return 在此集合中的元素上创建的Spliterator
* @since 1.8
*/
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, 0);
}
/**
* 返回一个以此集合作为源的顺序流。
*
* <p>当{@link #spliterator()}方法不能返回{@code IMMUTABLE}、{@code CONCURRENT}
* 或<em><a href="Spliterator.html#binding">late-binding</a></em>类型的spliterator时,
* 应该重写此方法。(有关详细信息,请参见{@link #spliterator()})。
*
* @implSpec
* 默认实现从集合的{@code Spliterator}创建一个顺序流。
*
* @return 包含此集合中的元素的顺序流
* @since 1.8
*/
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
/**
* 返回一个可能是并行的以此集合作为源的流。它允许该方法返回顺序流。
*
* <p>当{@link #spliterator()}方法不能返回{@code IMMUTABLE}、{@code CONCURRENT}
* 或<em><a href="Spliterator.html#binding">late-binding</a></em>类型的spliterator时,
* 应该重写此方法。(有关详细信息,请参见{@link #spliterator()})。
*
* @implSpec
* 默认实现从集合的{@code Spliterator}创建一个并行流。
*
* @return 可能是并行的以此集合作为源的流
* @since 1.8
*/
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
}