【JAVA學習筆記】18 泛型genericity Map集合

2018.4.19

泛型

泛型簡述。

[問題]

1.發現ArrayList可以放入任意類型的數據,但是實際操作中發現數據類型
 	不一致會導致更多的錯誤。
 	2.就是知道取出的數據是一個String類型,但是還是要通過【強轉】才能真正拿到想要的
 	String類型數據,這個操作很麻煩。

【期望】

集合中的數據類型能夠統一。
 	數據類型一致化問題。

【解決問題】

泛型
 	java jdk1.5之後的新特徵。

public class Demo1 {
	public static void main(String[] args) {
		ArrayList<Object> list = new ArrayList<Object>();
		
		list.add(new Demo1());//自定義類對象
		list.add("今天週四");
		list.add(3);
		
		
		System.out.println(list);
	
		Object object = list.get(1);
		
		String string = (String) object;
		System.out.println(string.length());
		System.out.println(string);
		
		Object[] arr = list.toArray();
		
		//Arrays.sort(arr);
		
		System.out.println(arr.toString());
	}
}

結果:
    [genericity.Demo1@6486b4d5, 今天週四, 3]
    4
    今天週四
    [Ljava.lang.Object;@47ca3f82

泛型實例

使用泛型來解決之前遇到的問題
 		1.解決集合中數據類型一致化問題,要求保存什麼數據就保存什麼數據,添加其他數據的話報錯。
 		異常提前。
 		2.從集合中取出數據,保存的是什麼類型,拿出來的就是什麼類型,不需要無意義的【強制類型轉換】。
 		
 標準格式:
 		ArrayList<String> list = new ArrayList<String>();  <E>佔位符。無意義
 以下情況也允許:
 	1.ArrayList list = new ArrayList<String>();
 	2.ArrayList<String> list = new ArrayList();
 	爲了照顧不同的版本和不同IDE工具。
 	
【 但是以下情況不允許】
	ArrayList<Object> list = new ArrayList<String>();
	ArrayList<String> list = new ArrayList<Object>();


public class Demo2 {
	public static void main(String[] args) {
		//<String>這是泛型,要求這個ArrayList集合中有且只能保存String類型的數據
		ArrayList<String>list = new ArrayList<String>();
		
		list.add("今天阿根廷被灌了6個球。");
		list.add("西班牙真牛逼");
		list.add("梅西提前離場了");
		
		
		//這裏無法保存除string類型之外的任意其他類型。
		//list.add(new Demo2());
		//list.add(1);
		
		String str = list.get(2);
		System.out.println(str);
	}
}

結果:

梅西提前離場了

泛型的運用

需求:
	定義一個方法,可以接受任意數據類型,而且要求返回的數據類型,就是你傳入的數據類型。
	例如:
		傳入String返回String
		傳入Demo3類型返回Demo3類型
		
泛型的使用需要:
	佔位符!<一個大寫字母>,只是一個佔位符,沒有實際含義,而且不同地方定義的佔位符沒有聯繫。
	
	
泛型在函數中使用的格式:
	修飾符<聲明的自定義泛型佔位符> 返回值類型(可以使用自定義泛型) 函數名(形式參數列表“也可以使用泛型”) {
		函數體
		在函數體中,所有用到自定義泛型的地方,都可以被替換 
	} 
	
包裝類:
	JAVA是完全面向對象的語言,在JAVA中萬物皆對象,如果是要保存類對象,那麼八大基本數據類型就無法使用,
	所以JAVA提供了一個包裝機制,包裝基本數據類型,讓他們成爲類對象,自動封箱。
	Integer --> int
	Byte --> byte
	Long --> long
	Short --> short
	
	Double --> double
	Float --> float
	
	Boolean --> boolean
	
	Character -> char
	
	如果使用包裝類直接賦值給普通的基本數據類型,這個操作稱之爲拆箱。

public class Demo3 {
	public static void main(String[] args) {
		String string = getType("String");
		Demo3 demo3 = getType(new Demo3());
		
		int num = getType(5);//integer int的包裝類。
		
	}

自定義泛型的佔位符<E>

<E>是自定義泛型的佔位符,表示在該函數中可以使用佔位符E,而E的具體數據類型,由傳入參數控制
 這樣操作可以讓函數多樣化,多元化,代碼更加簡單。


public static <E> E getType(E e) {
	
	return e;
}

}

類內使用泛型。

在類內使用泛型。

格式:

	class 類名<自定義泛型的佔位符> {
		//在這裏所用的泛型和用戶創建對象時聲明的一致。
	}
	
注意事項:
	1.一個類聲明的自定義泛型,如果在創建類對象時定了泛型的具,確體數據類型,那麼在整個類內所有用到
	該泛型佔位符的非靜態成員方法,使用的數據類型都是創建時創建的類型。
	
	2.如果創建使用了自定義泛型的類對象,但是沒有確定泛型的具體類型,那麼編譯器會把這個
	泛型認爲是Object類型。
	
	3.類中聲明的自定義泛型,不能在內的靜態方法使用,如果想讓靜態方法使用泛型,自己聲明自己使用
	類似於方法中使用泛型。
	
	4.建議:如果在代碼中出現了多個使用泛型的地方,請使用多個名字。 T E

class InvalidArrayException extends Exception {

	public InvalidArrayException(String message) {
		super(message);
	}
}

class invalidComparatoraException extends Exception {
	public invalidComparatoraException(String message) {
		super(message);
	}
}

class ArrayTools<A> {
	/**
	 * 利用泛型來滿足不同數據類型的排序算法,可以在創建類對象時約束!!
	 * @param array A類型,泛型的數組,可以是任意類型
	 * @param com	<? super A>是A類型的比較器或者其父類的比較器
	 * @throws InvalidArrayException	數組無效異常
	 * @throws invalidComparatoraException	比較器無效異常
	 */
	public void selectSortUsingCompare(A[] array,Comparator<? super A> com) throws InvalidArrayException, invalidComparatoraException {//?在A之上。
		//參數合法性判斷
		if(null == array || array.length == 0) {
			throw new InvalidArrayException("數組無效");
		}else if(null == com) {
			throw new invalidComparatoraException("比較器無效");
			
		}
		for (int i = 0; i < array.length - 1; i++) {
			int index = i;
			
			for(int j = i + 1;j <array.length;j++) {
				if(com.compare(array[index], array[j]) > 0) {
					index = j;
				}
			}
			if (index != i) {
				A tempA = array[index];
				array[index] = array[i];
				array[i] = tempA;
			}
		}
	}
	
	public void printArray(A[] array) {
		for (A a : array) {
			System.out.println(a);
		}
	}
  • 靜態成員方法加載的比類早,所以類聲明的泛型是在創建類的時候需求,是不能約束靜態方法的,是無關的,,可以在靜態方法中自己聲明泛型
public static <T> void test(T a) {
		System.out.println(a);
	}
	
}
public class Demo4 {
	public static void main(String[] args) 
			throws InvalidArrayException, invalidComparatoraException {
		Integer[] array = {1,3,5,6,7,8,2,4};
		
		ArrayTools<Integer> tools = new ArrayTools<Integer>();//
		
		//匿名內部類的匿名對象。  心臟是成員變量描述合適還是成員方法描述合適? 發動機對於汽車? 都不是,屬於成員內部類。
		tools.selectSortUsingCompare(array, new Comparator<Integer>() {

			@Override
			public int compare(Integer o1, Integer o2) {
				
				return o1 - o2;
			}			
		});
		
		tools.printArray(array);
		
	}
}

結果:

1
2
3
4
5
6
7
8

HashMap

---| Collection

------| List(接口)

---------| ArrayList(實現類)

---------| LinkedList(實現類)

------| Set(接口)

---------| HashSet(實現類)

---------| TreeSet(實現類)

比較器:
		Comparable接口 實現 compareTo方法
		Comparator接口 實現 compare方法
				
生活中,有關係的數據更多一點
	賬號 密碼
	鑰匙 鎖
	英文 解釋
	
	NSDictionary Objective-C Next Step公司。
	
	---| Map<K,V> 雙列集合,這是一個接口 Key值不能重複
	------| HashMap 實現類
	------| TreeMap 實現類
	
	K:key 鍵! 是一個不允許重複的唯一值。
	V: Value 值 一個鍵(key)對應一個值(value) 可以重複的
	
	在Map<K,V> 雙列集合中,保存的只能是一個鍵(key)值(value)對。
	
	
	Map中要學習的方法:
		增
			put(K key, V value);//添加一個鍵(K)值(value)對
			putAll(Map<? extends K,? extends V> map);//添加一個符合數據類型的Map雙列集合
		刪
			remove(Object key);//根據key刪除對應的鍵值對。
			clear();//清空所有鍵值對。
		改
			put(K key,V value);//當鍵key存在的時候,這個操作時重新修改值。size();//獲取鍵值對個數
			get(Object key);//通過鍵獲取對應的值value。
			containsKey(Object key);//查看這個key是否在Map中存在。
			containsValue(Object value);//查看這個value是否在map中存在
			
			keySet();//返回所有鍵(key)的set的集合
			values();//返回所有值(value)的Collection集合

public class Demo1 {
	public static void main(String[] args) {
		Map<String, String>map = new HashMap<String,String>();
		
		//使用put(k,v)添加元素
		map.put("薛之謙", "高磊鑫");
		map.put("鹿晗", "關曉彤");
		map.put("宋仲基", "宋慧喬");
		map.put("余文樂", "王棠雲");
		map.put("王寶強", "馬蓉");
		
		System.out.println(map);
		
		Map<String,String> map2 = new HashMap<String,String>();
		
		map2.put("科比", "瓦妮莎");
		
		//添加另一個Map
		map.putAll(map2);
		System.out.println(map);
		
		//清空當前map雙列集合
		map2.clear();
		System.out.println(map2.isEmpty());
		System.out.println(map2);
		
		//根據Key刪除對應的鍵值對
		map.remove("科比");
		System.out.println(map);
		
		//當key值存在時,這個操作是修改對應的value
		map.put("王寶強", null);
		System.out.println(map);
		
		System.out.println(map.size());
		
		System.out.println(map.containsKey("謝霆鋒"));
		System.out.println(map.containsKey("薛之謙"));
		
		System.out.println(map.containsValue("高磊鑫"));
		System.out.println(map.containsValue("王菲"));
		
		System.out.println(map.get("科比"));
		System.out.println(map.get("鹿晗"));
		
		Set<String> set = map.keySet();
	
		for (String string : set) {
			System.out.println(string);
		}
		System.out.println("........................");
		Collection<String> c = map.values();
		for (String string : c) {
			System.out.println(string);
		}
		System.out.println(c.toString());
	}
}

MAP集合遍歷

public class Demo1 {
	public static void main(String[] args) {
		HashMap<String, Integer> map = new HashMap<String,Integer>();
		
		map.put("macpro",28888);
		map.put("iphoneX", 8300);
		map.put("ipad pro",5190);
		
		System.out.println(map);
		
		//第一種遍歷方式,藉助於keySet
		
		Set<String> set = map.keySet();
		
		//使用Set集合的Iterator迭代器
		Iterator<String> it = set.iterator();
		while(it.hasNext()) {
			String key = it.next();//獲取每一個map中key值
			int value = map.get(key);
			
			System.out.println(key+"="+value);
			
		}
		//以上方法,其實不太合適,獲取的是key值,再藉助於Map裏面的get方法,獲取相應的value
		//並沒有獲取到完整的鍵值對。
		
		//第二種方式,藉助於values
		Collection<Integer> c = map.values();
		
		for (Integer i : c) {
			System.out.println(i);
		}
		
		//以上方法不合適,只能拿到value,不能獲得Key
		
		//在java中,萬物皆對象。[]
		
		/*
		 這裏把鍵值對認爲是一個對象組成一個類,稱之爲Entry。 
		 
		 class Entry<k,v> {
		 	K key;
		 	V value;
		 }
		 
		 //這裏可以認爲在map集合中,保存的每一個鍵值對都是一個entry對象,把這些entry對象獲取出來,
		   作成一個集合,進行遍歷。
		   entrySet();
		   map.Entry
		 */
		Set<Entry<String,Integer>> entrySet = map.entrySet();
		
		Iterator<Entry<String,Integer>> it2 = entrySet.iterator();
		
		while (it2.hasNext()) {
			System.out.println(it2.next());
		}
	}
}

泛型複習--------錯誤提前

爲了解決數據類型一致化的問題
避免沒有意義的強制類型轉換。

自定義泛型使用的格式
	<大寫字母> 一般用T E。
佔位符 沒有任何含義。

泛型在函數中的使用
		格式:
		權限修飾符<自定義泛型> 返回值類型(可以使用泛型) 函數名(形式參數列表“自定義泛型”) {
				同樣可以使用泛型
		}

泛型在類中使用
		格式:
		class 類名<自定義泛型> {
			非靜態的成員變量或者方法都可以使用類中定義的<自定義泛型>
			
			靜態方法不能使用類中自定義泛型,但是可以方法中自己定義泛型
		}
		
		Array.sort(T[] t,Comparator<? super T> c)
		
泛型在接口中的使用
		格式:
		interface 接口名<自定義泛型> {
				//成員變量 缺省屬性: public static final 必須初始化因爲final不可變
				//成員方法 缺省屬性: abstract
		}
		一個類遵從帶有自定義泛型的有兩種方式:
			例如:
				interface A<T> {
					public void testA(T t);
				}
				
			1.方式1class Test1<T> implements A<T> {
					public void testA(T t) {
					
					實現方法
					}
				}
			更加自由 在創建類對象時,纔對泛型進行約束。	
			
			2.方式2class Test implements A<String> {
					public void testA(String t) {
							//實現方法
						}
				}
			遵從接口時,接口直接確定了泛型的具體類型。
			
	
	泛型的上下限:
		<? super T>
			表示數據類型是T對象或者是其父類對象
		<? extends T>
				表示數據類型是T對象或者其子類對象
				
##Map
	Map<K,V> K不可重複,V可重複 1,1對應。
	---| HashMap
	---| TreeMap
	
	put(K key, V value);
	putAll(map<? extends k,? extends v> map);
	
	clear();
	remove(Object k);
	
	size();
	containsKey(object Key);
	containsValue(Object value);
	
	keySet();
	values();
	
	get(Object l);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章