Collection接口作为List, Set, Queue等的父类,在平时还是非常常用的。Java8在之前Collection接口的基础上,使用default关键字增加了一些非抽象方法。现在就着重来研究下。
首先看Collection接口的声明
public interface Collection extends Iterable
下面具体看看声明的方法。
1. int size() 方法
/**
* Returns the number of elements in this collection. If this collection
* contains more than Integer.MAX_VALUE elements, returns
* Integer.MAX_VALUE.
*
* @return the number of elements in this collection
*/
int size();
size() 方法返回Collection集合中元素的个数,返回值是int类型的,此方法的注释中写道,如果元素个数大于int能表示的最大数量,则只能返回int所能表示的最大数。
2. boolean isEmpty() 方法
这个很简答,就不说了
3. boolean contain(Object o) 方法
如果Collection中包含至少一个o对象,则返回true。
4. Iterator
/**
* Returns an iterator over the elements in this collection. There are no
* guarantees concerning the order in which the elements are returned
* (unless this collection is an instance of some class that provides a
* guarantee).
*
* @return an Iterator over the elements in this collection
*/
Iterator iterator();
返回此Collection的迭代器。迭代器并不能保证返回元素的顺序,除非继承Collection的实现类做了具体的实现来保证迭代器输出的顺序。
5. Object[] toArray() 方法
/**
* Returns an array containing all of the elements in this collection.
* If this collection makes any guarantees as to what order its elements
* are returned by its iterator, this method must return the elements in
* the same order.
*
* The returned array will be "safe" in that no references to it are
* maintained by this collection. (In other words, this method must
* allocate a new array even if this collection is backed by an array).
* The caller is thus free to modify the returned array.
*
*
This method acts as bridge between array-based and collection-based
* APIs.
*
* @return an array containing all of the elements in this collection
*/
Object[] toArray();
此方法将Collection元素返回成数组。值得注意的是,返回数组是重新分配空间储存的,实际就是所有元素的副本。调用者获取数据之后可以随意更改而不影响原集合。
6.
/**
* Returns an array containing all of the elements in this collection;
* the runtime type of the returned array is that of the specified array.
* If the collection fits in the specified array, it is returned therein.
* Otherwise, a new array is allocated with the runtime type of the
* specified array and the size of this collection.
*
* If this collection fits in the specified array with room to spare
* (i.e., the array has more elements than this collection), the element
* in the array immediately following the end of the collection is set to
* null. (This is useful in determining the length of this
* collection only if the caller knows that this collection does
* not contain any null elements.)
*
*
If this collection makes any guarantees as to what order its elements
* are returned by its iterator, this method must return the elements in
* the same order.
*
*
Like the {@link #toArray()} method, this method acts as bridge between
* array-based and collection-based APIs. Further, this method allows
* precise control over the runtime type of the output array, and may,
* under certain circumstances, be used to save allocation costs.
*
*
Suppose x is a collection known to contain only strings.
* The following code can be used to dump the collection into a newly
* allocated array of String:
*
*
* String[] y = x.toArray(new String[0]);
*
* Note that toArray(new Object[0]) is identical in function to
* toArray().
*
* @param the runtime type of the array to contain the collection
* @param a the array into which the elements of this collection are to be
* stored, if it is big enough; otherwise, a new array of the same
* runtime type is allocated for this purpose.
* @return an array containing all of the elements in this collection
* @throws ArrayStoreException if the runtime type of the specified array
* is not a supertype of the runtime type of every element in
* this collection
* @throws NullPointerException if the specified array is null
*/
T[] toArray(T[] a);
这个方法和前一个方法方法名相同,但是区别很大。首先,此方法是一个模板方法,可以动态指定类型,前一个方法只返回Object类型的数组;其次,前一个方法是新分配一段空间来储存复制对象,而此方法接受一个数组参数。
此函数接受一个数组参数,会尝试将元素放入指定的数组,如果类型可以成功转换,并且数组参数T[] a的空间足以放下所有元素,则将元素放入a中,如果a还有剩余空间,则填充为null。如果a空间不够,则会新建一个数组,并将元素转换为指定类型加入到数组中并返回。
例如
public void run() {
List orderList1 = new ArrayList();
orderList1.add(new Order("0001", "man", 100)); //Order(orderId, createdby, amount)
orderList1.add(new Order("0002", "man", 1000));
orderList1.add(new Order("0003", "man", 10000));
Order[] orderContainer1 = new Order[4];
Order[] orderContainer2 = orderList1.toArray(orderContainer1);
System.out.println(orderContainer1 == orderContainer2); //true
System.out.println(orderContainer1.length); //4
Order[] orderContainer3 = new Order[1];
Order[] orderContainer4 = orderList1.toArray(orderContainer3);
System.out.println(orderContainer1 == orderContainer3); //false
System.out.println(orderContainer3.length); //1
System.out.println(orderContainer4.length); //4
}
6. boolean add(E e) 方法
向Collection中添加一个元素。添加方式和具体实现相关,例如List可以添加重复元素,而向Set中添加重复元素返回就是false。
7. boolean remove(Object o) 方法
从Collection中移除一个元素。
8. boolean containsAll(Collection> c) 方法
如果Collection中包含所有c中的元素,则返回true。
9. boolean addAll(Collection> c) 方法
向Collection中添加所有c中的元素。
10. boolean removeAll(Collection> c) 方法
从Collection中删除所有c中的元素。
11. default boolean removeIf(Predicate super E> filter) 方法
/**
* Removes all of the elements of this collection that satisfy the given
* predicate. Errors or runtime exceptions thrown during iteration or by
* the predicate are relayed to the caller.
*
* @implSpec
* The default implementation traverses all elements of the collection using
* its {@link #iterator}. Each matching element is removed using
* {@link Iterator#remove()}. If the collection's iterator does not
* support removal then an {@code UnsupportedOperationException} will be
* thrown on the first matching element.
*
* @param filter a predicate which returns {@code true} for elements to be
* removed
* @return {@code true} if any elements were removed
* @throws NullPointerException if the specified filter is null
* @throws UnsupportedOperationException if elements cannot be removed
* from this collection. Implementations may throw this exception if a
* matching element cannot be removed or if, in general, removal is not
* supported.
* @since 1.8
*/
default boolean removeIf(Predicate super E> filter)
此方法是java 1.8版本之后添加的。default关键字允许在接口类中存在非抽象方法。参数接受一个Predicate类型的函数,通常是lambda表达式。
此函数作用是遍历整个Collection,删除符合Predicate filter的条目。
例如,
public void run() {
List orderList1 = new ArrayList();
orderList1.add(new Order("0001", "man", 100)); //Order(orderId, createdby, amount)
orderList1.add(new Order("0002", "man", 1000));
orderList1.add(new Order("0003", "man", 10000));
orderList1.removeIf((o)-> o.getAmount()> 100);
System.out.println(orderList1.size()); //1
}
上例中接受了lambda表达式(o)-> o.getAmount()> 100,此表达式判断order amount是否大于100,如果大于100就返回true。配合removeIf可以删除Collection中所有amount大于100的order。
12. boolean retainAll(Collection> c) 方法
只保留参数c中存在的元素,其他Collection中的参数都删除。
13. void clear() 方法
清楚Collection中所有元素。
14. boolean equals(Object o) 方法
判断对象o是否和Collection相等,具体相等的判断方法有实现类自己决定。
15. int hashCode() 方法
返回Collection的哈希值。
16. default Spliterator
这个又是Java 1.8 中新增的函数,使用default关键字提供了默认实现。此方法返回一个Spliterator,Spliterator也是Java 1.8 中引入的新的一种迭代器,除了拥有一般迭代器的遍历Collection功能,还可以对目标集合进行分割,这种分割特性特别适合多线程处理Collection。对于Spliterator可以参考https://blog.logentries.com/2015/10/java-8-introduction-to-parallelism-and-spliterator/,我也会在以后发表分析Spliterator的文章。举个小例子。
public void run() {
List orderList1 = new ArrayList();
Set orderSet1 = new HashSet<>();
for (int i = 0; i < 6; i++){
Order temp = new Order(String.valueOf(i), "man", 100);
orderList1.add(temp);
orderSet1.add(temp);
}
Spliterator orderSpliter = orderList1.spliterator();
Spliterator orderSpliter1 = orderSpliter.trySplit();
System.out.println(orderSpliter.getExactSizeIfKnown()); //结果3
System.out.println(orderSpliter1.getExactSizeIfKnown()); //结果3
}
以上代码使用Spliterator将一个数组列表分割了一次,得到一个大小为3的新的Spliterator (orderSpliter1),而原来的Spliterator也被分割(orderSpliter),从6变成了3。
17. default Stream
Java 1.8 的引入的方法,返回流对象,和我们之前的inputstream 和outputstream是不同的概念。借用Stream对象,可以方便的对集合进行聚合、大批量操作等等。它结合lambda表达式,可以简化代码,使用parallelStream充分利用多核计算机的计算能力,提高处理效率。之后我的博客也会详细分析Stream的原理和使用。
Collection接口在Java 1.8 中添加了很多新的功能,包括Spliterator、Stream、和结合lambda表达式的操作。感觉Java 1.8 中引入了很多令人兴奋的新内容,很值得我们仔细分析和研究。