java SE 1.8中Collection接口分析

Collection接口作为List, Set, Queue等的父类,在平时还是非常常用的。Java8在之前Collection接口的基础上,使用default关键字增加了一些非抽象方法。现在就着重来研究下。

首先看Collection接口的声明

public interface Collection<E> extends Iterable<E>

首先,Collection是一个模板接口,意味着能够接受各种对象作为元素类型。它继承了Iterable,因此,可以使用迭代器来遍历集合的元素。

下面具体看看声明的方法。

1. int size() 方法

/**
     * Returns the number of elements in this collection.  If this collection
     * contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
     * <tt>Integer.MAX_VALUE</tt>.
     *
     * @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<E> 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 <tt>Iterator</tt> over the elements in this collection
     */
    Iterator<E> 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.
     *
     * <p>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.
     *
     * <p>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. <T> T[] toArray(T[] a) 方法

/**
     * 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.
     *
     * <p>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
     * <tt>null</tt>.  (This is useful in determining the length of this
     * collection <i>only</i> if the caller knows that this collection does
     * not contain any <tt>null</tt> elements.)
     *
     * <p>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.
     *
     * <p>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.
     *
     * <p>Suppose <tt>x</tt> is a collection known to contain only strings.
     * The following code can be used to dump the collection into a newly
     * allocated array of <tt>String</tt>:
     *
     * <pre>
     *     String[] y = x.toArray(new String[0]);</pre>
     *
     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
     * <tt>toArray()</tt>.
     *
     * @param <T> 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> T[] toArray(T[] a);
这个方法和前一个方法方法名相同,但是区别很大。首先,此方法是一个模板方法,可以动态指定类型,前一个方法只返回Object类型的数组;其次,前一个方法是新分配一段空间来储存复制对象,而此方法接受一个数组参数。

此函数接受一个数组参数,会尝试将元素放入指定的数组,如果类型可以成功转换,并且数组参数T[] a的空间足以放下所有元素,则将元素放入a中,如果a还有剩余空间,则填充为null。如果a空间不够,则会新建一个数组,并将元素转换为指定类型加入到数组中并返回。

例如

public void run() {
		List<Order> orderList1 = new ArrayList<Order>();
		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<Order> orderList1 = new ArrayList<Order>();
		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<E> 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<Order> orderList1 = new ArrayList<Order>();
		Set<Order> 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<Order> orderSpliter = orderList1.spliterator();
		Spliterator<Order> 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<E> stream() 和 default Stream<E> parallelStream() 方法

Java 1.8 的引入的方法,返回流对象,和我们之前的inputstream 和outputstream是不同的概念。借用Stream对象,可以方便的对集合进行聚合、大批量操作等等。它结合lambda表达式,可以简化代码,使用parallelStream充分利用多核计算机的计算能力,提高处理效率。之后我的博客也会详细分析Stream的原理和使用。


Collection接口在Java 1.8 中添加了很多新的功能,包括Spliterator、Stream、和结合lambda表达式的操作。感觉Java 1.8 中引入了很多令人兴奋的新内容,很值得我们仔细分析和研究。



















没有更多推荐了,返回首页