Java集合框架复习

来源:互联网 发布:js购物车数量加减代码 编辑:程序博客网 时间:2024/05/16 17:36

List

ArrayList

使用如下代码,我们实例化了一个ArrayList类的对象:

ArrayList<Integer> list=new ArrayL<Integer>

查阅JDK源码就会发现,ArrayList空的构造函数事实上是调用了下面的构造函数:

 

 

public ArrayList(intinitialCapacity) {       super();       if(initialCapacity < 0)            thrownewIllegalArgumentException("Illegal Capacity:"+                                              initialCapacity);       this.elementData = newObject[initialCapacity];}

public ArrayList(intinitialCapacity) {

       super();

       if(initialCapacity < 0)

            thrownewIllegalArgumentException("Illegal Capacity:"+

                                              initialCapacity);

       this.elementData =newObject[initialCapacity];

}

 

 

其中,最关键的一个对象出现了,就是elementData,它是一个Object数组,

用来存放之后我们将要“add”的对象。

 

然后来看add方法:

 

/**    * Appends the specified element to the end of this list.    *    * @parame element to be appended to this list    * @return<tt>true</tt> (as specified by {@link Collection#add})    */   publicboolean add(E e) {       ensureCapacity(size + 1); // Increments modCount!!       elementData[size++] = e;       returntrue;}

/**

    * Appends the specified element to the end of this list.

    *

    * @parame element to be appended to this list

    * @return<tt>true</tt> (as specified by {@link Collection#add})

    */

   publicboolean add(E e) {

       ensureCapacity(size + 1); // Increments modCount!!

       elementData[size++] = e;

       returntrue;

}

 

首先,它去调用了一个名字叫做ensureCapacity的方法:

/**    * Increases the capacity of this <tt>ArrayList</tt>instance, if    * necessary, to ensure that it can hold at least the number of elements    * specified by the minimum capacity argument.    *    * @param   minCapacity  the desired minimum capacity    */   publicvoid ensureCapacity(int minCapacity) {       modCount++;       int oldCapacity = elementData.length;       if (minCapacity > oldCapacity) {           Object oldData[] = elementData;           int newCapacity = (oldCapacity * 3)/2 + 1;             if (newCapacity < minCapacity)              newCapacity= minCapacity;            //minCapacity is usually close to size, so this is a win:            elementData = Arrays.copyOf(elementData, newCapacity);       }    }

/**    * Increases the capacity of this <tt>ArrayList</tt>instance, if    * necessary, to ensure that it can hold at least the number of elements    * specified by the minimum capacity argument.    *    * @param   minCapacity  the desired minimum capacity    */   publicvoid ensureCapacity(int minCapacity) {       modCount++;       int oldCapacity = elementData.length;       if (minCapacity > oldCapacity) {           Object oldData[] = elementData;           int newCapacity = (oldCapacity * 3)/2 + 1;             if (newCapacity < minCapacity)              newCapacity= minCapacity;            //minCapacity is usually close to size, so this is a win:            elementData = Arrays.copyOf(elementData, newCapacity);       }    }


 

首先来看modCount,它是用来记录当前list对象被改变的次数的;

当第一次调用add方法,elementDatasize0,那么minCapacity

的值为1,一直到第十次调用addensureCapacity方法并没有去真正地

增大elementData的容量。直到第十一次调用add方法:modCount记录了

已经十一次修改list,接下来的oldCapacity(10)<minCapacity(11),于是list对象的

“新的容量”(newCapacity)被赋值为16,最后调用Arrays.copyOf对旧数组进行了

一份拷贝。

 

由于ArrayList内部使用数组实现,所以它长于随机访问,这也仅仅是针对其他集合对象而言的,与数组相比,效率会低很多。

 

LinkedList

LinkedList部分源码如下:

     privatetransient Entry<E> header = new Entry<E>(null, null, null);       privatetransientintsize =0;    /**    * Constructs an empty list.    */   public LinkedList() {       header.next = header.previous = header;}privatetransient Entry<E> header = new Entry<E>(null, null, null);       privatetransientintsize =0;    /**    * Constructs an empty list.    */   public LinkedList() {       header.next = header.previous = header;}


      

 

 

它是基于链表实现的,每个entry对象(节点)都包含自己本身的值与对前后两个节点的引用。

 

我们着重来看下addremove两个方法。

首先是add

publicbooleanadd(E e) {       addBefore(e, header);       returntrue;    } addBefore如下:private Entry<E> addBefore(Ee, Entry<E> entry) {       Entry<E>newEntry = newEntry<E>(e, entry, entry.previous);       newEntry.previous.next = newEntry;       newEntry.next.previous = newEntry;       size++;       modCount++;       return newEntry;    }


 

 

双向循环链表就像手拉手那样,每个节点都连接在一起,addremove开销较小。Remove方法如下:

private E remove(Entry<E> e) {       if (e == header)           thrownewNoSuchElementException();        E result = e.element;       e.previous.next = e.next;       e.next.previous = e.previous;       e.next =e.previous = null;       e.element = null;       size--;       modCount++;       returnresult;    }


 

而其代价便是短于随机访问。


Map

Map是一种强大的编程工具,它提供了将对象映射到另一个对象的能力(key---->value)。

HashMap

因为map中是key--->value这种键值对,所以它要求key是不可以重复的,value是可以重复的。就像下面的例子:

String[] strs={"a","b","c","c","d","a","e"};Map<String,Integer> result=new HashMap<String, Integer>();for(int i=0;i<strs.length;i++){result.put(strs[i], new Integer(1));}System.out.println(result);

上例使用了String作为Map的key,当“a”第二次放进map中时,它被忽略掉了。(此例引申后,我们可以使用它来统计一个字符串数组中,元素的出现次数。)

在能正确的使用map之前,还是要知道为什么它的key是不可以重复的,它是如何保证不能重复的。

查看JDK中HashMap的源码你就会发现:每当将一个对象“put”进map中,JDK都会拿这个对象和map中已经存在的对象进行比较,如下:

public V put(K key, V value) {        if (key == null)            return putForNullKey(value);        int hash = hash(key.hashCode());        int i = indexFor(hash, table.length);        for (Entry<K,V> e = table[i]; e != null; e = e.next) {            Object k;            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {                V oldValue = e.value;                e.value = value;                e.recordAccess(this);                return oldValue;            }        }        modCount++;        addEntry(hash, key, value, i);        return null;    }
那么两个key是否相同,取决于他们的equal方法和hashCode方法。众所周知,HashSet中存放的元素也是不会重复的,并且它是基于map实现的,

下面的例子重写了equals和hashCode方法:

package com.lemon.map;import java.util.HashSet;import java.util.Iterator;public class HashSetTest2 {public static void main(String[] args) {HashSet<StudentModel> set=new HashSet<StudentModel>();set.add(new StudentModel(new Integer(1),"Bill"));set.add(new StudentModel(new Integer(1),"Bill"));set.add(new StudentModel(new Integer(1),"Bill"));Iterator<StudentModel> it=set.iterator();while(it.hasNext()){System.out.println(it.next());}}}class StudentModel {private Integer id;private String name;public StudentModel(Integer id,String name) {this.id=id;this.name=name;}@Overridepublic String toString() {return "I am a student which id is["+id.intValue()+"] and name is["+name+"]";}@Overridepublic boolean equals(Object obj) {return obj instanceof StudentModel&&((StudentModel)obj).id.equals(id)&&((StudentModel)obj).name.equals(name);}@Overridepublic int hashCode() {int result=17;int c=new Integer(id).hashCode()+name.hashCode();result=37*result+c;return result;}}


TreeMap

 

 

原创粉丝点击