Java集合框架复习

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( int initialCapacity) {

       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;
	}
	@Override
	public String toString() {
		return "I am a student which id is["+id.intValue()+"] and name is["+name+"]";
	}
	@Override
	public boolean equals(Object obj) {
		return obj instanceof StudentModel&&((StudentModel)obj).id.equals(id)&&((StudentModel)obj).name.equals(name);
	}
	@Override
	public int hashCode() {
		int result=17;
		int c=new Integer(id).hashCode()+name.hashCode();
		result=37*result+c;
		return result;
	}
	
	
	
	
}


TreeMap

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值