TreeSet以有序狀態保持並可防止重復
HashMap可用成對的name/value來保存與取出
LinkedList針對經常插入或刪除中間元素所設計的高效率集合
HashSet防止重復的集合,可快速地找尋相符的元素
LinkedHashMap類似HashMap,但可以記住元素插入的順序,也可以設定成依照元
素上次存取的先後來排序
可以使用TreeSet或Collections.sort()方法來排序
ArrayList是最常用的泛型化類型,有兩個關鍵部分:類的聲明和新增元素的方
法的聲明
Sort()方法只能接受Comparable對象的list
Collections.sort()會把list中的String依照字母排序
以泛型的觀點來說,extend代表extend or implement,代表“是壹個。。。”
,且適用於類和接口
調用單壹參數的sort(List o)方法代表由list元素上的comparetTo()方法來決定
順序。因此元素必須要實現Comparable這個接口
調用sort(List o,Comparator c)方法代表不會調用list元素的compareTo()方法
,而會使用Comparator的compare()方法,這意味著list元素不需要實現Comparable.
LIST:是壹種索引位置的集合
SET:註重獨壹無二的性質,不允許重復的集合
MAP:使用成對的鍵值和數據值,值可重復,但KEY不可
如果foo與bar兩對象相等,則foo.equals(bar)會返回true,且兩者的hashCode()
也會返回相同的值。要讓Set能把對象視為重復的,就必須讓它們符合上面的條件。
hashCode()與equals()的相關規定:
1)如果兩個對象相等,則hashcode必須也是相等的。
2)如果兩個對象相等,對其中壹個對象調用equals()必須返回true。也就是說
,若a.equals(b)則b.equals(a).
3)如果對象有相同的hashcode值,它們也不壹定是相等的。但若兩個對象相等
,則hashcode值壹定是相等的。
4)因此若equals()被覆蓋過,則hashcode()也必須被覆蓋。
5)hashcode()的默認行為是對在heap上的對象產生獨特的值.妳沒有override過
hashcode(),則該class的兩個對象怎樣都不會被認為是相同的。
6)equals()的默認行為是執行==的比較。也就是說會去測試兩個引用是否對
上heap上同壹個對象。如果equals()沒有被覆蓋過,兩個對象永遠都不會被視為相同的,
因為不同的對象有不同的字節組合。
a.equals()必須與a.hashCode()==b.hashCode()等值。
但a.hashCode()==b.hashCode()不壹定要與a.equals()等值。
要使用TreeSet,下列其中壹項必須為真:
TreeSet集合中的元素必須是有實現Comparable的類型
或
使用重載、取用Comparator參數的構造函數來創建TreeSet.
MAP中的元素實際上是兩個對象,關鍵字和值。值可以重復,但是關鍵字不可。
如果方法的參數是Animal的數組,它也能夠取用Animal次類型的數組。
也就是說,如果方法是這樣聲明的:void foo(Animal[] a){}
若Dog有extend過Animal,妳就可以用下列的兩種方式調用:
foo(anAnimalArray);
foo(aDogArray);
數組的類型是在運行期間檢查的,但集合的類型檢查只會發生在編譯期間
在方法參數中使用萬用字符時,編譯器會阻止任何可能破壞引用參數所指集合的
行為。妳能夠使用list中任何元素的方法,但不能加入元素。也就是說,妳可以操作集合
元素,但不能新增集合元素。如此才能保障執行期間的安全性,因為編譯器會阻止執行期
的恐怖行動。所以下面這個程序是可以的:
for(Animal a:animals){
a.eat();
}
但這個就過不了編譯:
animals.add(new Cat());
--------------------
程序代碼:
=========================================
SongList.txt
----------------------------------
Communication/The Cardingans
Black Dog/Led Zeppelin
Dreams/Van Halen
Comfortably Numb/Pink Floyd
Beth/Kiss
倒退嚕/黃克林
=========================================
記錄KTV最常點的歌,沒有排序功能
import java.util.*;
import java.io.*;
public class Jukebox1{
//歌曲名稱存在String的ArrayList上
ArrayList<String> songList= new ArrayList<String>();
public static void main(String[] args){
new Jukebox1.go();
}
//這個方法會載入文件並列出內容
public void go(){
getSongs();
System.out.println(songList);
}
//讀取文件的程序
void getSongs(){
try{
File file=new File("SongList.txt");
BufferedReader reader=new BufferedReader(new
FileReader(file));
String line=null;
while(line=reader.readLine())!=null){
addSong(line);
}
}catch(Exception ex){ex.printStackTrace();}
}
void addSong(String lineToParse){
//split()方法會用反斜線來拆開歌曲內容
String[] tokens=lineToParse.split("/");
//因為只需要歌名,所以只取第壹項加入SongList
songList.add(tokens[0]);
}
}
====
//依照加入的順序列出,與原始的文本文件順序相同。
輸出:
%java Jukebox1
[Communication,Black Dog,Dreams,Comfortably Numb,Beth,倒退嚕]
-----------------------------------------------------------------
對點歌系統加上Collections.sort()
import java.util.*;
import java.io.*;
public class Jukebox1{
//歌曲名稱存在String的ArrayList上
ArrayList<String> songList= new ArrayList<String>();
public static void main(String[] args){
new Jukebox1.go();
}
//這個方法會載入文件並列出內容
public void go(){
getSongs();
System.out.println(songList);
Collections.sort()(songList);
System.out.println(songList);
}
//讀取文件的程序
void getSongs(){
try{
File file=new File("SongList.txt");
BufferedReader reader=new BufferedReader(new
FileReader(file));
String line=null;
while(line=reader.readLine())!=null){
addSong(line);
}
}catch(Exception ex){ex.printStackTrace();}
}
void addSong(String lineToParse){
//split()方法會用反斜線來拆開歌曲內容
String[] tokens=lineToParse.split("/");
//因為只需要歌名,所以只取第壹項加入SongList
songList.add(tokens[0]);
}
}
====
輸出:
%java Jukebox1
[Communication,Black Dog,Dreams,Comfortably Numb,Beth,倒退嚕]
[Beth,Black Dog,Comfortably Numb,Communication,Dreams,倒退嚕]
-------------------------------------------------------------
現在要用song對象而不只是string
class Song{
//對應四種屬性的四個實例變量
String title;
String artist;
String rating;
String bpm;
Song(String t, String a,String r,String b){
//變量都會在創建時從構造函數中設定
title=t;
artist=a;
rating=r;
bpm=b;
}
//四種屬性的getter
public String getTitle(){
retrun title;
}
public String getArtist(){
retrun artist;
}
public String getRating(){
retrun rating;
}
public String getBpm(){
retrun bpm;
}
//將toString()覆蓋過,讓它返回歌名
public String toString(){
return title;
}
}
=========================================
SongList.txt
----------------------------------
Communication/The Cardingans/5/80
Black Dog/Led Zeppelin/4/84
Dreams/Van Halen/6/20
Comfortably Numb/Pink Floyd/5/110
Beth/Kiss/4/100
倒退嚕/黃克林/5/90
=========================================
說明:新的歌曲文件帶有四項屬性,所以我們需要創建出Song的實例變量來帶這些屬性。
修改點歌系統程序
import java.util.*;
import java.io.*;
public class Jukebox1{
//將String改成Song類型
ArrayList<Song> songList= new ArrayList<Song>();
public static void main(String[] args){
new Jukebox1.go();
}
//這個方法會載入文件並列出內容
public void go(){
getSongs();
System.out.println(songList);
Collections.sort()(songList);
System.out.println(songList);
}
//讀取文件的程序
void getSongs(){
try{
File file=new File("SongList.txt");
BufferedReader reader=new BufferedReader(new
FileReader(file));
String line=null;
while(line=reader.readLine())!=null){
addSong(line);
}
}catch(Exception ex){ex.printStackTrace();}
}
void addSong(String lineToParse){
//split()方法會用反斜線來拆開歌曲內容
String[] tokens=lineToParse.split("/");
//使用解析出來 的四項屬性來創建Song對象並加入到list中
Song nextSong =new Song(tokens[0],tokens[1],tokens[2],tokens[3]);
songList.add(nextSong);
}
}
====
輸出:
%javac Jukebox3.java
Jukebox3.java:15:cannot find symbol
symbol :method sort(java.util.ArrrayList<Song>)
location:class java.util.Collections
Collections.sort(songList);
1 error
關於泛型
1)創建被泛型化類的實例
創建ArrayList時妳必須要指定它所容許的對象。
new ArrayList<Song>()
2)聲明與指定泛型類型的變量
List<Song> songList = new ArrayList<Song>()
3)聲明(與調用)取用泛型類型的方法
void foo(List<Song> list)
x.foo(songList)
---------------------------------------------
ArrayList的類型參數
下面這行程序:
ArrayList<String> thisList = new ArrayList<String>
代表這個ArrayList:
public class ArrayList<E> extends AbstractList<E>...{
public boolean add(E o)
//更多代碼
}
會被編譯器這樣看待:
public class ArrayList<String> extends AbstractList<String>...{
public boolean add(String o)
//更多代碼
}
-------------------------------------------------------------------
運用泛型的方法
1)使用定義在類聲明的類型參數。
public class ArrayList<E> extends AbstractList<E>...{
public boolean add(E o)
}
2)使用未定義在類聲明的類型參數
//<T extends Animal> 為方法聲明的壹部分,表示任何被聲明為Animal或Animal的子型
public <T extends Animal> void takeThing(ArrayList<T> list)
//public void takeThing(ArrayList<Animal> list)表示只有ArrayList<Animal>合法。
-----------------------------------------------------------------------------
public static <T extends Comparable<? super T>> void sort(List<T> list)
//T extends Comparable表示它必須是Comparable
//? super T表示Comparable的類型參數必須是T或T的父型
//List<T>表示僅能傳入繼承Comparable的參數化類型的list
-----------------------------------------------------------------------------
class Song implements Comparable<Song>{
//對應四種屬性的四個實例變量
String title;
String artist;
String rating;
String bpm;
//Song s為要比較的對象
public int compareTo(Song s){
return title.compareTo(s.getTitle());
}
Song(String t, String a,String r,String b){
//變量都會在創建時從構造函數中設定
title=t;
artist=a;
rating=r;
bpm=b;
}
//四種屬性的getter
public String getTitle(){
retrun title;
}
public String getArtist(){
retrun artist;
}
public String getRating(){
retrun rating;
}
public String getBpm(){
retrun bpm;
}
//將toString()覆蓋過,讓它返回歌名
public String toString(){
return title;
}
}
====
調用sort()方法後會把Song依照字母作排序
輸出:
%java Jukebox3
[Communication,Black Dog,Dreams,Comfortably Numb,Beth,倒退嚕]
[Beth,Black Dog,Comfortably Numb,Communication,Dreams,倒退嚕]
---------------------------------------------------------------
用Comparator更新點歌系統
我們在新版本做了三件事:
1)創建並實現Comparator的內部類,以compare()方法取代compareTo()方法
2)制作該類的實例
3)調用重載版的sort(),傳入歌曲的list以及Comparator的實例。
import java.util.*;
import java.io.*;
public class Jukebox5{
//將String改成Song類型
ArrayList<Song> songList= new ArrayList<Song>();
public static void main(String[] args){
new Jukebox5.go();
}
//創建江實現Comparator的內部類,註意到類型參數和要比較的類型是相符的
//one.getArtist()會返回String,compareTo以String來比較
class ArtistCompare implements Comparator<Song>{
public int compare(Song one,Song two){
return one.getArtist().compareTo(two.getArtist());
}
}
//這個方法會載入文件並列出內容
public void go(){
getSongs();
System.out.println(songList);
Collections.sort()(songList);
System.out.println(songList);
//創建Comparator的實例,調用sort(),傳入list與Comparator對象
ArtistCompare artistCompare = new ArtistCompare();
Collections.sort(songList,artistCompare);
System.out.println(songList);
}
//讀取文件的程序
void getSongs(){
try{
File file=new File("SongList.txt");
BufferedReader reader=new BufferedReader(new
FileReader(file));
String line=null;
while(line=reader.readLine())!=null){
addSong(line);
}
}catch(Exception ex){ex.printStackTrace();}
}
void addSong(String lineToParse){
//split()方法會用反斜線來拆開歌曲內容
String[] tokens=lineToParse.split("/");
//使用解析出來 的四項屬性來創建Song對象並加入到list中
Song nextSong =new Song(tokens[0],tokens[1],tokens[2],tokens[3]);
songList.add(nextSong);
}
}
-----------------------------------------------------------------
以HashSet取代ArrayList
import java.util.*;
import java.io.*;
public class Jukebox6{
ArrayList<Song> songList= new ArrayList<Song>();
public static void main(String[] args){
new Jukebox6.go();
}
public void go(){
//這個方法沒有更新,所以它還是會把Song加到ArrayList中
getSongs();
System.out.println(songList);
Collections.sort()(songList);
System.out.println(songList);
//創建參數化的HashSet來保存Song,addAll()可以復制其他集合的元素
HashSet<Song> songSet = new HashSet<Song>();
songSet.addAll(songList);
System.out.println(songSet);
}
//getSongs() and addSong() methods
}
-------------------------------------------------------------------
有覆蓋過hashCode()與equals()的Song類
class Song{
String title;
String artist;
String rating;
String bpm;
//Object aSong為要比較的對象
public boolean equals(Object aSong){
Song s = (Song) aSong;
//因為歌名是String,且String本來就喜笑顏開過的equals(),所以我們可調用
return getTitle().equals(s.getTitle());
}
public int hashCode(){
//String也有覆蓋過的hashCode(),註意到hashCode()與
//equals()使用相同的實例變量
return title.hashCode();
}
public int compareTo(Song s){
return title.compareTo(s.getTitle());
}
Song(String t, String a,String r,String b){
//變量都會在創建時從構造函數中設定
title=t;
artist=a;
rating=r;
bpm=b;
}
//四種屬性的getter
public String getTitle(){
retrun title;
}
public String getArtist(){
retrun artist;
}
public String getRating(){
retrun rating;
}
public String getBpm(){
retrun bpm;
}
//將toString()覆蓋過,讓它返回歌名
public String toString(){
return title;
}
}
-----------------------------------------------------------
如果想要保持有序,使用TreeSet
import java.util.*;
import java.io.*;
public class Jukebox8{
ArrayList<Song> songList= new ArrayList<Song>();
int val;
public static void main(String[] args){
new Jukebox8.go();
}
public void go(){
getSongs();
System.out.println(songList);
Collections.sort()(songList);
System.out.println(songList);
//調用沒有參數的構造函數來用TreeSet取代HashSet意味著
//以對象的compareTo()方法來進行排序
TreeSet<Song> songSet = new TreeSet<Song>();
//使用addAll()可以把對象全部加入
songSet.addAll(songList);
System.out.println(songList);
}
//讀取文件的程序
void getSongs(){
try{
File file=new File("SongList.txt");
BufferedReader reader=new BufferedReader(new
FileReader(file));
String line=null;
while(line=reader.readLine())!=null){
addSong(line);
}
}catch(Exception ex){ex.printStackTrace();}
}
void addSong(String lineToParse){
//split()方法會用反斜線來拆開歌曲內容
String[] tokens=lineToParse.split("/");
//使用解析出來 的四項屬性來創建Song對象並加入到list中
Song nextSong =new Song(tokens[0],tokens[1],tokens[2],tokens[3]);
songList.add(nextSong);
}
}
-----------------------------------
public <T extends Animal> void takeThing(ArrayList<T> list)
與
public void takeThing(ArrayList<? extends Animal>list)是壹樣的~