在編程的過程中,多數據的存儲及應用都是比較麻煩的事,以前我就只知道用數組和自己寫封裝類來解決,但是這兩種方法在一些功能中並不適用,比如我們要根據數據庫中其中一個表的數據弄一個下拉菜單的內容,這個時候我們需要從數據庫獲取顯示給用戶看的內容及對應的id。在這種情況中,因為在數據庫中的這種一對的數據一般都是有好幾個的,所以封裝類並不適用,而數組只能存儲單一的一種數據類型,並且只能通過游標獲取對應的值,還有最麻煩的是數組在初始化的時候必須初始化長度,所以也數組也不太適用,這個時候我們可以使用java官方提供的容器類(集合類)。
容器類(集合類)是java官方提供給我們的存儲方式,它擴展了數組使用上的自由度,如:長度可變,可存儲多種數據類型的數據等。容器類在java體系中並不僅僅是一個類,而是很多的容器類所構成的一個框架、體系,不同的容器類具有不同的存儲方式,因為容器類太多,所以java官方制定了一系列接口,所有的容器類都得已實現。
常用的容器類大致可分為三大類:List、Set、Map
首先介紹一下List:
List是有順序的,其中常用的主要有Vector、ArrayList、LinkedList三個容器類,List的主要使用方法如下:
//ArrayList ls=new ArrayList();
//更多情況是如下定義
List ls=new ArrayList();
//問題: 為什么要這樣定義?
//某些情況下面,可能需要切換實現類
//LinkedList ls=new LinkedList();//改變太大,如果,下面有人調用到List接口沒有方法
//List ls=new LinkedList();//不管換什么實現類,都沒問題,因為接口沒變
//-----------------------------------------------------------------------------------
//List 可以存放任意類型的數據
//其實,所有類都是Object類的子類,存入的時候,將所有類型都打散成為Object
//因此,拿出來的時候,肯定需要轉換
String a="a";
int i=10;
double d=1000.0;
ls.add(a);
ls.add(i);
ls.add(d);
//有順序,可以根據元素的索引/游標訪問元素
String a2=(String)ls.get(0);
//int i2=(int)ls.get(1);//int 是基本數據類型,不是封裝類,沒法直接轉換
int i2=(Integer)ls.get(1);
double d2=(Double)ls.get(2);
//如果是jdk1.5以上,可以使用泛型
//泛型:限制只能存儲某一類型
List<String> ls2=new ArrayList<String>();
ls2.add("a");
ls2.add("b");
ls2.add("c");
String s=ls2.get(0);//無須再轉換
//-----------------------------------------------------------------------------------
//你接到一個別人發過來的List,如何取出里面所有數據
for(int j=0;j<ls2.size();j++){
System.out.println(ls2.get(j));
}
//或者轉換成迭代器遍歷出來
Iterator it=ls2.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
而在上面提到的三個常用的List容器類中,ArrayList和Vector都是使用數組方式存儲數據,這兩個容器類都是通過使用數組實現的,所以索引數據速度快,但是由於插入數據時涉及數組元素移動等內存操作,所以插入數據速度較慢,而由於Vector中的方法都是線程安全的,即所有方法都添加了同步鎖synchronized,所以性能上要比ArrayList要差。
LinkedList是使用雙向鏈表實現存儲的,在索引數據時需要進行向前或向后的遍歷,但是在插入數據時只需記錄本項的前后項即可,所以其索引數據慢插入數據快。
Set是無序的,其中是不能包含重復元素的,其中常用的主要有:HashSet、TreeSet,Set的主要使用方法如下:
Set hs=new HashSet();//不能插入重復數據
//List hs = new ArrayList();//可以插入重復數據
Student s=new Student(1,"zhangsan");
hs.add(s);
s.name="edit";
boolean isAdded = hs.add(s); //重復數據,不能再插入
System.out.println(isAdded); //false
hs.add(new Student(2,"lisi"));
hs.add(new Student(3,"wangwu"));
hs.add(new Student(1,"zhangsan"));//這不是重復數據,是一個新的對象
//-----------------------------------------------------------------------------------
//無順序,只能迭代取值,順序會有不一定的情況。
Iterator it=hs.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
HashSet是無順序的,而TreeSet是有順序的,但是TreeSet的順序與List那樣按插入的先后排序不同,它是按照元素對象自己定義的排序規則進行排序的,因此前者允許放入null,且效率較高,而后者不允許放入null,且效率較低。
Map是以鍵值對的方式存儲數據的一種容器類,其中常用的主要有:HashMap、HashTable、TreeMap,Map的主要使用方法如下:
HashMap hm=new HashMap();
//HashMap<String,String> hm=new HashMap<String,String>();
String a="a";
int i=10;
double d=1000.0;
//put(鍵,值)
hm.put("zfc",a);
hm.put("zx",i);
hm.put(3,d);
//hm.put(3,12.0); //key相同,覆蓋已有value
String a2=(String)hm.get("zfc");
int i2=(Integer)hm.get("zx");
double d2=(Double)hm.get(3);
System.out.println(a2+" "+i2+" "+d2);
//遍歷方式1:建議方式,效率高一些
Iterator iterator = hm.keySet().iterator();//Iterator迭代器,按key來迭代遍歷
while(iterator.hasNext()) {
System.out.println(hm.get(iterator.next()));
}
//遍歷方式2
Iterator it = hm.entrySet().iterator();//Iterator迭代器,按entry來迭代遍歷
while(it.hasNext()){
java.util.Map.Entry entry = (java.util.Map.Entry)it.next();
// entry.getKey() 返回與此項對應的鍵
// entry.getValue() 返回與此項對應的值
System.out.println(entry.getValue());
}
HashMap允許有空鍵(null)與空值(null),非線程安全,效率較高。
HashTable不允許有空鍵(null)與空值(null),線程安全,效率較低。
TreeMap能把其保存的記錄根據key排序(類似TreeSet),默認是按照key的默認排序,但也可指定排序的比較器,在用迭代器迭代遍歷時,得到的記錄是排序以后的,TreeMap不允許有空鍵(null)但可以有空值(null)。

