一、 集合框架中的接口
所謂框架就是一個類庫的集合。集合框架就是一個用來表示和操作集合的統一的架構,包含了實現集合的接口與類。
二、List接口主要有2個實現類:ArrayList、LinkedList
·ArrayList
1. ArrayList 底層採用數組實現,但是用不帶參數的構造方法生產 ArrayList 對象時,實際上會在底層生成一個長度爲 10 的 Object 類型的數組。 如果增加的元素超過10個,那麼ArrayList底層會新生成一個數組,長度爲原數組的1.5倍+1,然後將原數組的內容複製到新數組當中,並且後續增加的內容都會放到新數組當中。當新數組無法容納增加的元素時,重複該過程。
2. 對於 ArrayList 元素的刪除操作,需要將被刪除元素的後續元素向前移動,代價比較高。
3. 集合當中只能放置對象的引用,無法放置原生數據類型,我們需要使用原生數據類型的包裝類才能加入到集合當中。
4. 集合當中放置的都是 Object 類型,因此取出來的也是 Object 類型,那麼必須要使用強制類型轉換將其轉換爲真正的類型(放置進去的類型)。
·LinkedList
1. LinkedList 底層主要由雙向鏈表實現。
2. 添加數據:LinkedList list = new LinkedList(); list.add("elements");
當向 ArrayList 添加啊一個對象時,實際上就是將該對象放置到了 ArrayList 底層所維護的數組當中;當向 LinkedList 中添加一個對象時,實際上 LinkedList 內部會生成一個Entry 對象,該 Entry 對象的結構爲:
// Entry類的僞代碼
Entry{
Entry prevoius;
Object element;
Entry next;
}
Entry entry = new Entry();
entry.element = "elements";
list.add(entry);
其中的 Object 類型的元素 element 就是我們向 LinkedList 中所添加的元素,然後 Entry 又構造好了向前與向後的引用 previous、next,最後將生成的這個Entry 對象加入到了鏈表當中。換句話說,LinkedList 中所維護的是一個個的Entry 對象。· 關於ArrayList 與 LinkedList 的比較分析:
a) ArrayList 底層採用數組實現,LInkedList 底層採用雙向鏈表實現。
b) 當執行插入或者刪除操作時,採用 LinkedList 比較好。
c) 當執行搜索操作時,採用 ArrayLIst 比較好。
三、 Set 接口
Set的特點:1. 是無序的、沒有重複的。
set接口實現類常用的是HashSet。
package com.bob.set;
import java.util.HashSet;
public class SetTest2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
HashSet set = new HashSet();
/*
set.add(new People("zhangsan"));
set.add(new People("lisi"));
set.add(new People("zhangsan"));
People p1 = new People("zhangsan");
set.add(p1);
set.add(p1);
*/
String s1 = new String("a");
String s2 = new String("a");
set.add(s1);
set.add(s2);
System.out.println(set);
}
}
class People{
String name;
public People(String name){
this.name = name;
}
}
1. 關於 Object 類的 equals 方法的特點(Object 的 equals 方法是比較兩個對象是否相等)。
在一個非空的對象引用上它實現一個相等性的關係,它滿足以下條件:
a) 自反性:x.equals(x)應該返回 trueb) 對稱性:x.equals(y)爲 true,那麼 y.equals(x)也爲 true。
c) 傳遞性:x.equals(y)爲 true 並且 y.equals(z)爲 true,那麼 x.equals(z)也應該爲 true。
d) 一致性:x.equals(y)的第一次調用爲 true,那麼 x.equals(y)的第二次、第三次、第 n次調用也應該爲 true,前提條件是在比較之間沒有修改 x 也沒有修改 y。
e) 對於非空引用 x,x.equals(null)返回 false。
注意:通常重寫 equals() 方法的時候我們也會 重寫 hashCode() 方法,這樣以保證對hashCode()方法的一般性契約,表明相等的對象也有相同的hash Code
2. Object 類中的 hashCode() 方法:
定義: public int hashCode(); 返回一個對象的 hash code 值。這個方法是爲了更好的支持 java.util.Hashtable 這個類。
關於 Object 類的 hashCode()方法的特點:
a) 在 Java 應用的一次執行過程當中,對於同一個對象的 hashCode 方法的多次調用,他們應該返回同樣的值(前提是該對象的信息沒有發生變化) 。
b) 對於兩個對象來說,如果使用 equals 方法比較返回 true,那麼這兩個對象的 hashCode值一定是相同的。
c) 對於兩個對象來說,如果使用 equals 方法比較返回 false,那麼這兩個對象的 hashCode值不要求一定不同(可以相同,可以不同) ,但是如果不同則可以提高應用的性能。
d) 對於 Object 類來說,不同的 Object 對象的 hashCode 值是不同的(Object 類的 hashCode值表示的是對象的地址) 。
3. 當使用 HashSet 時, hashCode()方法就會得到調用,判斷已經存儲在集合中的對象的hash code 值是否與增加的對象的 hash code 值一致;如果不一致,直接加進去;如果一致,再進行 equals 方法的比較,equals 方法如果返回 true,表示對象已經加進去了,就不會再增加新的對象,否則加進去。(所以當調用set 的 add() 方法的時候底層是通過 hashCode() 和 equals() 方法共同協作完成的。)
4. 如果我們重寫 equals 方法,那麼也要重寫 hashCode 方法,反之亦然。
//覆寫hashCode()和equals()方法實現比較人名相同就不添加對象
package com.bob.set;
import java.util.HashSet;
public class SetTest3 {
public static void main(String[] args) {
HashSet set = new HashSet();
Student s1 = new Student("zhangsan");
Student s2 = new Student("zhangsan");
set.add(s1);
set.add(s2);
System.out.println(set);
}
}
class Student{
String name;
public Student(String name){
this.name = name;
}
//override hashCode method
public int hashCode(){
return this.name.hashCode();
}
//override equals method
public boolean equals(Object obj){
if(this == obj){
return true;
}
if(null != obj && obj instanceof Student){
Student s = (Student)obj;
if(name.equals(s.name)){
return true;
}
}
return false;
}
}
//也可使用eclipse工具自動生成這2個方法。Source-->generate hashCode() and equals();
以上例子中取出來的都是[....]對象,如果想要取出對象的屬性需要使用 HashSet 中的 iterator() 方法,此方法返回類型爲 iterator 接口(可以使用子類實現接口方式返回此類型) 。iterator() 方法定義在 Iterable 接口中,因爲Collection 接口是 iterable 的子接口,所以所有類集中都包含iterator()方法。
package com.bob.set;
import java.util.HashSet;
import java.util.Iterator;
public class IteratorTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
HashSet set = new HashSet();
set.add("a");
set.add("b");
set.add("c");
set.add("d");
// 使用 Iterator必須先調用HashSet類的iterator()方法返回一個Iterator對象
// Iterator iter = set.iterator();
//
// while(iter.hasNext()){
// String value = (String)iter.next();
// System.out.println(value);
// }
for(Iterator iter = set.iterator(); iter.hasNext();){
String value = (String)iter.next();
System.out.println(value);
}
// 對於Set一般採取迭代器(遍歷)方式取得元素。
// List也可以通過這種方式取得,但是一般list直接使用下標操縱更加方便。
}
}
5. Set的子接口:SortedSet
SortedSet 中主要常用類:TreeSet
//將對象排序
package com.bob.set;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
public class TreeSetTest2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
TreeSet set = new TreeSet(new PersonComparator()); // 按照此種實例方法規則排序
Person p1 = new Person(10);
Person p2 = new Person(20);
Person p3 = new Person(30);
Person p4 = new Person(40);
set.add(p1);
set.add(p2); // 向TreeSet添加對象TreeSet會自動跟裏面已有對象進行比較
set.add(p3);
set.add(p4);
for (Iterator iter = set.iterator(); iter.hasNext();) {
Person p = (Person) iter.next();
System.out.println(p.score);
}
}
}
class Person {
int score;
public Person(int score) {
this.score = score;
}
public String toString() {
return String.valueOf(this.score);
}
}
// 自定義比較規則
class PersonComparator implements Comparator {
@Override
public int compare(Object o1, Object o2) {
// compare()方法返回值意思:
// <0,arg0 < arg1。 arg1在arg0前面
// =0, arg0 == arg1
// <0, arg0 > arg1
Person p1 = (Person) o1; // 集合中放置的是什麼類型就轉換成什麼類型
Person p2 = (Person) o2;
return -(p1.score - p2.score); // 根據返回值來進行排序
}
}
Collections 靜態類
package com.bob.set;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
public class CollectionsTest {
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.add(new Integer(-3));
list.add(new Integer(-1));
list.add(new Integer(-9));
list.add(new Integer(3));
list.add(new Integer(13));
//使用Collections類中的reverseOrder()方法進行反序
Comparator cmr = Collections.reverseOrder();
Collections.sort(list, cmr);
for(Iterator iter = list.iterator(); iter.hasNext();){
System.out.println(iter.next() + " ");
}
System.out.println("#####################");
//將集合打亂
Collections.shuffle(list);
for(Iterator iter = list.iterator(); iter.hasNext();){
System.out.println(iter.next() + " ");
}
//打印最大數和最小數
System.out.println("minimum value:" + Collections.min(list));
System.out.println("maximum value:" + Collections.max(list));
}
}
四 、 Map(映射)
1. map是一個對象,它會將鍵映射到它的值上。一個 map 不能包含重複的鍵,一個鍵最多映射一個值。(值可以是重複的)
2. Map 的 keySet() 方法返回 Key 的集合, 因爲 Map 的鍵是不能重複的的,因此 keySet()方法的返回類型是 Set;而 Map 的值是可以重複的,因此 values() 方法的返回類型是 Collection, 可以容納重複的元素。
keySet() 方法返回所有鍵的集合。返回一個 Set 類型,因爲 Set 裏面的元素是不能重複的。
values() 方法返回一個 Collection 類型,因爲 Collection 是可以重複的。
// put() get() keySet()
package com.bob.set;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
public class MapTest3 {
public static void main(String[] args) {
HashMap map = new HashMap();
map.put("a", "aa");
map.put("b", "bb");
map.put("c", "cc");
map.put("d", "dd");
map.put("e", "ee");
//使用keySet()獲取所有key的集合,遍歷所有key,或者key對於的值
Set set = map.keySet();
for(Iterator iter = set.iterator() ; iter.hasNext(); ){
String key = (String)iter.next();
String value = (String)map.get(key);
System.out.println(key + "=" + value);
}
}
}
//使用entrySet()方式實現。Map接口中的成員變量Map.Entry類型
package com.bob.set;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class MapTest5 {
public static void main(String[] args) {
HashMap map = new HashMap();
map.put("a", "aa");
map.put("b", "bb");
map.put("c", "dd");
map.put("c", "dd");
//獲取entry對象,entry對象裏面包含了key和value一對的映射視圖
Set set = map.entrySet();
//map.entrySet返回的類型是Map.Entry
for(Iterator iter = set.iterator(); iter.hasNext(); ){
Map.Entry entry = (Map.Entry)iter.next();
String key = (String)entry.getKey();
String value = (String)entry.getValue();
System.out.println(key + " : " + value);
}
}
}
3. TreeMap
TreeMap類不僅實現了Map接口,還實現了Map接口的子接口java.util.SortedMap。
五、HashSet 與 HashMap 源代碼
1. HashSet 底層是用 HashMap 實現的。當使用 add() 方法將對象添加到 Set 當中時, 實際上是將該對象作爲底層所維護的 Map 對象的 key,而 value 則都是同一個 Object 對象(該對象我們用不上);
2. HashMap 底層會維護一個數組,我們向 HashMap 中放置的對象實際上是存儲在該數組中。
3. 當向 HashMap 中 put 一對鍵值時,它會根據 key 的 hashCode 值計算出一個位置,該位置就是此對象準備往數組中存放的位置。如果該位置沒有對象存在,就將此對象直接放進數組中; 如果該位置已經有對象存在了,則順着此存在的對象的鏈開始尋找(Entry 類有一個 Entry 類型的 next 成員變量,指向了該對象的下一個對象),如果該鏈上有對象的話,在去使用 equals 方法進行比較,如果對此鏈上的某個對象的 equals 方法比較爲 false,則將該對象放到數組當中,然後將數組中該位置以前存在的那個對象鏈接到此對象的後面(根據操作系統原理,當前被使用的元素,在不久的將來更有可能會被使用,所以替換了之前的位置)。
HashMap 的內存實現佈局