一 我所知道的集合
我知道的第一個集合:ArrayList,加入元素非常方便,add(Object elem)。其它的, TreeSet(有序并防止重復), HashMap(名值對), LinkedList(為經常插入或刪除中間元素所設計的高效集合), HashSet(防止重復,可快速找尋符合的元素), LinkedHashMap(類型于HashMap, 但可以記住元素插入的順序,也可以設定成依照元素上次存取的先后來排序)。總的來說,這些集合可以用“順序”和“重復”來區分。
下面兩圖用來說明3個主要的接口:List, Set 和 Map.(部分)

二 順序
順序問題,可以用TreeSet或Collections.sort()來實現。當插入新元素時,TreeSet會花時間找到適當的位置,所以相對要慢了。而ArrayList只要把新加的元素放到最后就好。(當然,ArrayList也有重載的add(index, element )可以插到指定位置,也慢,通常不這樣做。)
sort(List<T> list) 方法 /* public static <T extends Comparable<? super T>> void sort(List<T> list) */ :只傳入Comparable 接口的 list 作為參數。Comparable有一個方法要實現:compareTo(T o)方法。
或者用重載的sort()方法:sort(List<T> list, Comparator< ? super T> c)方法 。這樣,就用不著compareTo()方法了。而是要實現Comparator接口,實現compare()方法。
實例1-關于 sort(List<T> list)

/**//* Class StudyComparable */
package conllection;

import java.util.Collections;
import java.util.LinkedList;


public class StudyComparable
{
LinkedList<Person> psn = new LinkedList<Person>();


public static void main(String[] args)
{
StudyComparable sc = new StudyComparable();
sc.go();
}


private void go()
{
psn.add(new Person("one", 3));
psn.add(new Person("two", 2));
psn.add(new Person("three", 5));
psn.add(new Person("five", 6));
psn.add(new Person("eight", 8));
System.out.println(psn);
Collections.sort(psn);
System.out.println(psn);
}
}



/**//* Class Person */

package conllection;


public class Person implements Comparable<Person>
{
String name;
int age;


public Person(String n, int a)
{
name = n;
age = a;
}

@Override

public int compareTo(Person o)
{
return name.compareTo(o.name);
}

@Override

public String toString()
{
return name + "/" + age;
}
}

運行結果:
[one/3, two/2, three/5, five/6, eight/8]
[eight/8, five/6, one/3, three/5, two/2]
現在,可以按照name來排序了,不過我想用age 來排序,就要改代碼,用Person類中的compareTo()方法進入age的比較。這樣做很不好,所以可以用重載的sort(List<T> list, Comparator<? super T> c)方法。
實例2-關于 sort(List <T> list, Comparator <? super T> c)
Class StudyComparator
package conllection;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;


public class StudyComparator
{
ArrayList<Person> psn = new ArrayList<Person>();


public static void main(String[] args)
{
StudyComparator sc = new StudyComparator();
sc.go();
}


class NameComparator implements Comparator<Person>
{

@Override

public int compare(Person o1, Person o2)
{
return o1.name.compareTo(o2.name);
}

}


class AgeComparator implements Comparator<Person>
{

@Override

public int compare(Person o1, Person o2)
{
return o1.age - o2.age;
}

}


private void go()
{
psn.add(new Person("one", 3));
psn.add(new Person("two", 2));
psn.add(new Person("three", 5));
psn.add(new Person("five", 6));
psn.add(new Person("eight", 8));
System.out.println(psn);

NameComparator nc = new NameComparator();
Collections.sort(psn, nc);
System.out.println("onName:" + psn);
AgeComparator ac = new AgeComparator();
Collections.sort(psn, ac);
System.out.println("onAge:" + psn);
}
}

Class Person:同例1中的Person.Class 。因為在StudyComparator里面定義了Comparator的實現類,所以Person類不用動,也就是說,在沒有原代碼的情況下也實現了sort,而且可按不同的屬性來進行排序,我更喜歡這個重載的sort()方法。
運行結果:
[one/3, two/2, three/5, five/6, eight/8]
onName:[eight/8, five/6, one/3, three/5, two/2]
onAge:[two/2, one/3, three/5, five/6, eight/8]
三 重復
1 相等 ==
防止重復,用Set。要解決的第一個問題:兩個對象的引用怎樣才算是重復?答案就是它們是相等的。那么怎樣算‘相等’?顯然不是單純的值相等。‘相等’包括引用相等和對象相等。
引用相等:引用堆上的同一對象的兩個引用是相等的。如果對兩個引用調用hashCode() ,會得到相同的結果。hashCode()(默認的行為)會返回對象在堆上的特有的唯一序號。顯然,不同對象的引用的hashCode()的值是不同的。
對象相等:堆上的兩個不同對象,在意義上相同。
因此,
想要兩個不同的對象‘相等’,就必須要override hashCode()和equals()方法。
a.equals(b) 的默認行為是執行‘==’,包括了hashCode()的對比。如果equals()方法不被override, 那么兩個對象永遠都不會視為相同。
2 HashSet 檢查重復:hashCode() 與 equals()
當把對象放入HashSet時,它會先用對象的hashCode()與已有元素的hashCode()來比較,(如果沒有override過hashCode()方法,那么HashSet 會認為對象間不重復,我們當然要override來確保對象有相同的值)。如果hashCode()相同,再調用其中一個的equals()來檢查對象是否真的相同。如果又相同了,那么加入的操作就不會發生。
說明:有相同hashCode()的對象也不一定是相等的,感覺有點怪,但的確如此。因為hashCode()用的是雜湊算法,也許剛好使多個對象有了相同的雜湊值。越爛的雜湊算法越容易碰撞。這個屬于數據結構方面的問題了。具體的要問專家了。
posted on 2008-07-09 02:47
BlueSunshine 閱讀(1205)
評論(3) 編輯 收藏 所屬分類:
學習心得