在类集之前,想保存数组的话就只能是使用对象数组。但是数组有长度的限制,而如果使用链表这种数据结构的话,又会比较麻烦。类集框架就是来解决上面的问题的,就是实现一个动态的数组,包装上数据结构,因此就会有类集的出现。类集接口有collection,map,List,set,Iterator,ListIterator,Enumeraation,
SortedMap,Queue,Map.Entry,在面试时就会经常遇到前面四个的问题。
一、Collection接口
Collection接口的定义如下
public interface Collectionextends Iterable
从接口的定义可以看出来,这里是使用的泛型的定义,避免发生ClassCastException的异常。Collection接口是单值的存放最大父接口,可以向其中保存多个对象。继承于Iterable接口,Iterable接口已经是最大的接口了, 它主要是告诉我们它是可以进行迭代的。
public interface Iterable{
Collection接口的所有方法如下:
/*2017/11/3:这两天在看码的时候才注意到一个小细节,那就是这个集合定义的许多方法都是返回的boolean类型,之前都没有注意到过。看下面的代码,其中的一个add方法,增加值的时候是这样增加的,先把这个list的容量加1,然后把数据才赋进去,前面两步没有问题的时候才会返回true,表面增加成功。源码中大部分的方法都是这样的。*/
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
遍历Collection接口,不论Collection的实际类型如何,因为他是继承于Iterable接口,所以它都支持一个iterator()的方法,该方法返回一个迭代子,使用该迭代子即可逐一访问Collection中每一个元素:
Iterator it=collection.iterator();//获得一个迭代子while(it.hasNext()){Objectobj=it.next();//得到下一个元素}
也可以使用foreach输出
for(元素类型t 元素变量x : 遍历对象obj){ 引用了x的java语句;}for (String x : list) { System.out.println(x); }
Collection接口虽然是集合的最大接口,但是如果直接使用Colllection接口进行操作,则表示操作的含义不明确,因此会一般使用他的子接口。Collection的子接口有List,Set,Queue,和SortedSet四个。List可以存放重复的内容,Set不能存放重复的内容,所有重复的内容靠hashCode()和equals()两个方法区别。
二、List接口
List是Collection的子接口,其中可以保存各个重复的内容。接口的定义:
public interface Listextends Collection
List接口扩充了Collection接口,拥有比其更为广泛的方法,List接口的所有扩展方法如下:
1、ArrayList子类
ArrayList子类可以为List接口进行实例化。ArrayList继承了AbstractList类,
public class ArratListextends AbstractList implements List ,RandomAccess,Cloneable,Serializable
而AbstractList类实现了List接口。
public abstract class AbstractListextends AbstractCollection implements List
因此可以直接使用ArrayList为List接口进行实例化。
public class ArrayListAdd { public static void main(String []args){ ListallList=new ArrayList (); Collection allCollection=new ArrayList (); allList.add("hello"); allList.add(0,"world");//在0位置添加元素 System.out.println(allList);//[world, hello] allCollection.add("hi"); allCollection.add("MLDN"); allList.addAll(allCollection);//在最后添加元素 allList.addAll(0, allCollection);//在0位置添加元素 System.out.println(allList);//[hi, MLDN, world, hello, hi, MLDN] }}
每一个list都会被赋一个初始的容量,初始容量为10
/** * Constructs an empty list with an initial capacity of ten. */
从上面的结果可以看出来,使用List中的add(int index,E)方法可以在集合中的指定位置增加元素,而add(E)只是在最后面添加。
remove()方法可以去除指定位置的元素,或者去除指定内容的元素。
allList.remove(0);//移除System.out.println(allList);//[MLDN, world, hello, hi, MLDN]allList.remove("MLDN");System.out.println(allList);//[world, hello, hi, MLDN]allList.remove("MLDN");System.out.println(allList);//[world, hello, hi]
每次可以去除一个对象remove(Object o),每次去除一组对象removeAll(Collection<?> c),如果有多个相同类型的元素则需要多次去除;
通过取得长度的方法size(),然后使用get()方法可以将集合的指定位置的内容输出。
System.out.println(allList.size());//3System.out.println(allList.get(1));//hello
通过头Array()方法可以将集合变为数组。以及截取集合subList(int,int)方法,是否为空isEmpty()方法,查找字符串位置indexOf(String)方法等。
2、Vector子类
Vector子类是比较老的一个类了,同样是继承于AbstractList<E>接口,
public class Vectorextends AbstractList implements List , RandomAccess, Cloneable, java.io.Serializable{
因为和arraylist的区别不大,测试代码就不写了,arraylist是异步处理,是非线程安全的,只能使用Iterable和foreach输出。而Vector是同步出来,是线程安全的,可以使用Iterable,Enumeration和foreach输出
3、Linkedlist
LinkedList是一个链表的操作类,定义如下
public class LinkedListextends AbstractSequentialList implements List , Deque , Cloneable, java.io.Serializable
这个类不仅实现了list接口还实现了Duque接口,双向队列(Deque),是Queue的一个子接口,双向队列是指该队列两端的元素既能入队(offer)也能出队(poll),如果将Deque限制为只能从一端入队和出队,则可实现栈的数据结构。对于栈而言,有入栈(push)和出栈(pop),遵循先进后出原则,Queue接口是队列接口,是先进先出的方式。也就是说LinkedList类是双向列表,列表中的每个节点都包含了对前一个和后一个元素的引用.
public interface Dequeextends Queue {/**A linear collection that supports element insertion and removal at * both ends. The name deque is short for "double ended queue"
最后Queue接口是实现了Collection接口
public interface Queueextends Collection {
通过上面可以看到LinkedList类是双向列表,列表中的每个节点都包含了对前一个和后一个元素的引用.这个类的两个构造方法
public LinkedList() { }//生成空的链表public LinkedList(Collection c) { this(); addAll(c); }// 复制构造函数
其实现的方法也比较多,这里就不一一介绍了,需要用的时候查一下就行了。
三 set接口
set接口也是collection接口的子接口,但是和他们不一样的地方就是它不能包含不一样的重复的对象元素。
1、HashSet子类
hashset是set接口的子类,存放的元素是无序但不可重复。
public static void main(String[] args) { // TODO 自动生成的方法存根 SetallSet=new HashSet (); allSet.add("a"); allSet.add("a"); allSet.add("b"); allSet.add("b"); allSet.add("b"); allSet.add("c"); allSet.add("f"); allSet.add("s"); allSet.add("d"); System.out.println(allSet);//调用tostring()方法 }输出[a, b, c, s, d, f]
2、TreeSet子类
TreeSet子类是set接口的子类,存放的元素是有序而且也不可以重复。这里的有序是指在输入数据以后他会进行一个自动的排序。
public class TreeSetextends AbstractSet implements NavigableSet , Cloneable, java.io.Serializable{
他是继承了AbstractSet类,AbstractSet类又实现了Set接口
public abstract class AbstractSetextends AbstractCollection implements Set {
下面是最简单的一个TreeSet的测试
Setallset=new TreeSet (); allset.add("s"); allset.add("a"); allset.add("a"); allset.add("b"); allset.add("b"); allset.add("b"); allset.add("c"); allset.add("f"); allset.add("s"); allset.add("d"); System.out.println(allset);输出结果[a, b, c, d, f, s]
TreeSet的排序看起来就是这样,它会将所有非重复的元素就行排序,然后存储起来。我们看它的源码,在调用add方法以后,首先通过判断已经存储了这个值,然后他会返回一个boolean值。
public boolean add(E e) { return m.put(e, PRESENT)==null; }
未完待续。。。。