Collection
自我的自制力不强,所以用每天一个博客来要求自己,学习JDK的源码,今天就从java.util中最常用的Collection看。
- -
1.类介绍:
Colleciton是集合的顶级接口。使程序员操作成批的数据或对象元素极为方便。这些接口和类有很多对抽象数据类型操作的API,而这是我们常用的且在数据结构中熟知的。例如Map,Set,List等。并且Java用面向对象的设计对这些数据结构和算法进行了封装,这就极大的减化了程序员编程时的负担。程序员也可以以这个集合框架为基础,定义更高级别的数据抽象,比如栈、队列和线程安全的集合等,从而满足自己的需要。
这是源码上的注释,下面列出了集合的类型
* @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
其中
Collection<–List<–Vector
Collection<–List<–ArrayList
Collection<–List<–LinkedList
Collection<–Set<–HashSet
Collection<–Set<–HashSet<–LinkedHashSet
Collection<–Set<–SortedSet<–TreeSet
Map<–SortedMap<–TreeMap
Map<–HashMap
这是类头,E代表着泛型,继承一个Iterable接口为set创建迭代器而做准备。
public interface Collection<E> extends Iterable<E> {
这给Iterable类,并不是java.util下的,而是java.lang包下的一个Iterable接口,这个类下就一个迭代方法,返回的却是java.util.Iterator,这两个类真的容易看出,猜测set通过这个方法得到了迭代器,下面是Iterable源码:
public interface Iterable<T> {
/**
* Returns an iterator over a set of elements of type T.
*
* @return an Iterator.
*/
Iterator<T> iterator();
}
现在就需要看下Iterator迭代器了,iterator中就三个方法:
Iterator就相当于一个带有指针的序列,下面是我画的草图:
public interface Iterator {
boolean hasNext();
E next();
void remove();
}
boolean hasNext();使用了这个方法,迭代器判断序列是否到底了,如果到底返回false,如果没有返回True。
E next(); 得到指针指向的那一行的值,并且指针下移(ArrayList中是这样)。下面是ArrayList中的next源码
public E next() {
checkForComodification();
//当前的指针,其实就是数组的下标
int i = cursor;
//如果当前下标比总的size大,就抛异常
if (i >= size)
throw new NoSuchElementException();
//当前的元素数据
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
//最后下标+1
cursor = i + 1;
//但返回的还是当前没加过1的
return (E) elementData[lastRet = i];
}
- void remove(); 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。每次调用 next 只能调用一次此方法。如果进行迭代时用调用此方法之外的其他方式修改了该迭代器所指向的 collection,则迭代器的行为是不确定的。
List<String> list = new ArrayList<String>();
list.add( "0" );
list.add( "1" );
list.add( "2" );
list.add( "3" );
list.add( "4" );
list.add( "5" );
list.add( "6" );
list.add( "7" );
list.add( "8" );
list.add( "9" );
list.add( "10" );
list.add( "11" );
list.add( "12" );
list.add( "13" );
list.add( "14" );
list.add( "15" );
list.add( "16" );
list.add( "17" );
list.add( "18" );
list.add( "19" );
list.add( "20" );
int i = 0;
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String next = it.next();
//如果是偶数就删除
if ( i % 2 == 0 ) {
it.remove();
}
i++;
System.out.println(next);
}
Iterator<String> it1 = list.iterator();
while (it1.hasNext()) {
String next = it1.next();
i++;
System.out.println(next);
}
}
得到的结果是这样的第一个的迭代,输出1-20,但在其中把偶数都给删除了,而且删除的不是官方解释说的返回的最后一个元素。而是删除当前指针指向的位置的值。当初我以为数据都存在Iterator迭代器中,观看ArrayList源码得知,数据还是存在ArrayList中,Iterator删除的也是ArrayList中的值。所以第二次,重新使用ArrayList产生迭代器,数据只有奇数了。
这就要提到Iterator设计模式了,即迭代器设计模式。它的定义是
Provide a way to access the elements of an aggregate object sequentially without exposing its
underlying representation.(它提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节。)
简单地说,迭代器就类似于一个数据库中的游标,可以在一个容器内上下翻滚,遍历所有它需要查看的元素。
其实我们对ArrayList用的foreach就是调用了迭代器。
2.方法介绍:
-
1.Object[] toArray();和 <T>T[] toArray(T[] a);
- 1.1 Object[] toArray();是当前的集合对象转换为一个Object数组
-
1.2 <T> T[] toArray(T[] a); 是传入一个T类型的集合,这里的T指的是泛型,这里我说下类的泛型是<E>,那为什么这个T可以用呢,因为这个前面加了<T>,告诉了用T。
剩下就是这些常见的方法了:
int size();//得到集合长度
boolean isEmpty();//集合是否为空
boolean contains(Object o);//集合中有没有这个元素
Iterator<E> iterator();//产生迭代器
boolean add(E e);//添加
boolean remove(Object o);//移除
boolean containsAll(Collection<?> c);//全匹配类似this包含c就可以
boolean addAll(Collection<? extends E> c);//把c中的都添加
boolean removeAll(Collection<?> c);//移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。意思就是删除交集
boolean retainAll(Collection<?> c);//仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。意思是就保留交集
void clear();//删除全部
boolean equals(Object o);
int hashCode();