天天看點

Java基礎總結篇---Map接口

Map

将鍵映射到值的對象,一個映射不能包含重複的鍵,每個鍵最多隻能映射到一個值。除此之外你得明确的是Map是一個接口你得使用實作Map的類來執行個體化。其次是Map中資料存儲格式是K-V鍵值對方法存儲。

Map接口和Collection接口的不同

  • Map是雙列的,Collection是單列的
  • Map的鍵唯一,Collection的子體系Set是唯一的
  • Map集合的資料結構值針對鍵有效,跟值無關
  • Collection集合的資料結構是針對元素有效

Map集合常用功能

  • 添加功能
    • V put(K key,V value):添加元素。
      • 如果鍵是第一次存儲,就直接存儲鍵值對元素,傳回null
      • 如果鍵不是第一次存在,就用值把以前的值替換掉,傳回以前的值
  • 删除功能
    • V remove(Object key):根據鍵删除鍵值對元素,并把值傳回
  • 判斷功能
    • boolean containsKey(Object key):判斷集合是否包含指定的鍵
    • boolean containsValue(Object value):判斷集合是否包含指定的值
    • boolean isEmpty():判斷集合是否為空
  • 擷取功能
    • Set<Map.Entry<K,V>> entrySet():傳回此映射中包含的映射關系的 Set 視圖,也就是傳回一個鍵值對整體。
    • V get(Object key):根據鍵擷取值
    • Set keySet():擷取集合中所有鍵的集合
    • Collection values():擷取集合中所有值的集合
  • 長度功能
    • int size():傳回集合中的鍵值對的對數

代碼執行個體

public class MapDemo {
		public static void main(String[] args) {
			// 建立集合對象
			Map<String, String> map = new HashMap<String, String>();
	
			// 添加元素
			// System.out.println("put:" + map.put("文章", "馬伊俐"));
			// System.out.println("put:" + map.put("文章", "姚笛"));
	
			map.put("鄧超", "孫俪");
			map.put("黃曉明", "楊穎");
			map.put("周傑倫", "蔡依林");
			map.put("劉恺威", "楊幂");
	
			// void clear():移除所有的鍵值對元素
			// map.clear();
	
			// V remove(Object key):根據鍵删除鍵值對元素,并把值傳回
			// System.out.println("remove:" + map.remove("黃曉明"));
			// System.out.println("remove:" + map.remove("黃曉波"));
	
			// boolean containsKey(Object key):判斷集合是否包含指定的鍵
			// System.out.println("containsKey:" + map.containsKey("黃曉明"));
			// System.out.println("containsKey:" + map.containsKey("黃曉波"));
	
			// boolean isEmpty():判斷集合是否為空
			// System.out.println("isEmpty:"+map.isEmpty());			
			//int size():傳回集合中的鍵值對的對數
			System.out.println("size:"+map.size());
	
			// 輸出集合名稱
			System.out.println("map:" + map);
		}
	}
           

擷取功能:

public class MapDemo2 {
		public static void main(String[] args) {
			// 建立集合對象
			Map<String, String> map = new HashMap<String, String>();
	
			// 建立元素并添加元素
			map.put("鄧超", "孫俪");
			map.put("黃曉明", "楊穎");
			map.put("周傑倫", "蔡依林");
			map.put("劉恺威", "楊幂");
	
			// V get(Object key):根據鍵擷取值
			System.out.println("get:" + map.get("周傑倫"));
			System.out.println("get:" + map.get("周傑")); // 傳回null
			System.out.println("----------------------");
	
			// Set<K> keySet():擷取集合中所有鍵的集合
			Set<String> set = map.keySet();
			// 周遊Set 增強for 或者疊代器 反正就是Collection的周遊方式
			for (String key : set) {
				System.out.println(key);
			}
			System.out.println("----------------------");
	
			// Collection<V> values():擷取集合中所有值的集合
			Collection<String> con = map.values();
			for (String value : con) {
				System.out.println(value);
			}
		}
	}
           
Java基礎總結篇---Map接口

Map集合的周遊:

周遊思路一: A:擷取所有的鍵–> B:周遊鍵的集合,擷取得到每一個鍵 -->C:根據鍵去找值。

示例:

// 建立集合對象
		Map<String, String> map = new HashMap<String, String>();
	
		// 建立元素并添加到集合
		map.put("楊過", "小龍女");
		map.put("郭靖", "黃蓉");
		map.put("楊康", "穆念慈");
		map.put("陳玄風", "梅超風");
	
		// 周遊
		// 擷取所有的鍵
		Set<String> set = map.keySet();
		// 周遊鍵的集合,擷取得到每一個鍵
		for (String key : set) {
			// 根據鍵去找值
			String value = map.get(key);
			System.out.println(key + "---" + value);
		}

           
周遊思路二: A:擷取所有鍵值對對象的集合–>B:周遊鍵值對對象的集合,得到每一個鍵值對對象–>C:根據鍵值對對象擷取鍵和值。

示例:

// 建立集合對象
		Map<String, String> map = new HashMap<String, String>();

		// 建立元素并添加到集合
		map.put("楊過", "小龍女");
		map.put("郭靖", "黃蓉");
		map.put("楊康", "穆念慈");
		map.put("陳玄風", "梅超風");

		// 擷取所有鍵值對對象的集合
		Set<Map.Entry<String, String>> set = map.entrySet();
		// 周遊鍵值對對象的集合,得到每一個鍵值對對象
		for (Map.Entry<String, String> me : set) {
			// 根據鍵值對對象擷取鍵和值
			String key = me.getKey();
			String value = me.getValue();
			System.out.println(key + "---" + value);
		}
           

圖示對比:

Java基礎總結篇---Map接口

HashMap

鍵是哈希表結構,可以保證鍵的唯一性.需要注意的是當鍵為類類型的時候,需要重寫類的equals和hashcode方法.
Java基礎總結篇---Map接口
public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
           

LinkedHashMap

Map 接口的哈希表和連結清單實作,具有可預知的疊代順序。此實作與 HashMap 的不同之處在于,後者維護着一個運作于所有條目的雙重連結清單。此連結清單定義了疊代順序,該疊代順序通常就是将鍵插入到映射中的順序(插入順序)。
Java基礎總結篇---Map接口

TreeMap

鍵是紅黑樹結構,可以保證鍵的排序和唯一性。無參構造則是自然排序,前面的文章說過了。

示例:

// 建立集合對象
		TreeMap<Student, String> tm = new TreeMap<Student, String>(
				new Comparator<Student>() {
					@Override
					public int compare(Student s1, Student s2) {
						// 主要條件
						int num = s1.getAge() - s2.getAge();
						// 次要條件
						int num2 = num == 0 ? s1.getName().compareTo(
								s2.getName()) : num;
						return num2;
					}
				});

		// 建立學生對象
		Student s1 = new Student("潘安", 30);
		Student s2 = new Student("柳下惠", 35);
		Student s3 = new Student("唐伯虎", 33);
		Student s4 = new Student("燕青", 32);
		Student s5 = new Student("唐伯虎", 33);

		// 存儲元素
		tm.put(s1, "宋朝");
		tm.put(s2, "元朝");
		tm.put(s3, "明朝");
		tm.put(s4, "清朝");
		tm.put(s5, "漢朝");

		// 周遊
		Set<Student> set = tm.keySet();
		for (Student key : set) {
			String value = tm.get(key);
			System.out.println(key.getName() + "---" + key.getAge() + "---"
					+ value);
		}
           

統計字元串中每個字元出現次數:

圖解思路
Java基礎總結篇---Map接口
示例代碼
/*
	 * 需求 :"aababcabcdabcde",擷取字元串中每一個字母出現的次數要求結果:a(5)b(4)c(3)d(2)e(1)
	 * 
	 * 分析:
	 * 		A:定義一個字元串(可以改進為鍵盤錄入)
	 * 		B:定義一個TreeMap集合
	 * 			鍵:Character
	 * 			值:Integer
	 * 		C:把字元串轉換為字元數組
	 * 		D:周遊字元數組,得到每一個字元
	 * 		E:拿剛才得到的字元作為鍵到集合中去找值,看傳回值
	 * 			是null:說明該鍵不存在,就把該字元作為鍵,1作為值存儲
	 * 			不是null:說明該鍵存在,就把值加1,然後重寫存儲該鍵和值
	 * 		F:定義字元串緩沖區變量
	 * 		G:周遊集合,得到鍵和值,進行按照要求拼接
	 * 		H:把字元串緩沖區轉換為字元串輸出
	 * 
	 * 錄入:linqingxia
	 * 結果:result:a(1)g(1)i(3)l(1)n(2)q(1)x(1)
	 */
	public class TreeMapDemo {
		public static void main(String[] args) {
			// 定義一個字元串(可以改進為鍵盤錄入)
			Scanner sc = new Scanner(System.in);
			System.out.println("請輸入一個字元串:");
			String line = sc.nextLine();
	
			// 定義一個TreeMap集合
			TreeMap<Character, Integer> tm = new TreeMap<Character, Integer>();
			
			//把字元串轉換為字元數組
			char[] chs = line.toCharArray();
			
			//周遊字元數組,得到每一個字元
			for(char ch : chs){
				//拿剛才得到的字元作為鍵到集合中去找值,看傳回值
				Integer i =  tm.get(ch);
				
				//是null:說明該鍵不存在,就把該字元作為鍵,1作為值存儲
				if(i == null){
					tm.put(ch, 1);
				}else {
					//不是null:說明該鍵存在,就把值加1,然後重寫存儲該鍵和值
					i++;
					tm.put(ch,i);
				}
			}
			
			//定義字元串緩沖區變量
			StringBuilder sb=  new StringBuilder();
			
			//周遊集合,得到鍵和值,進行按照要求拼接
			Set<Character> set = tm.keySet();
			for(Character key : set){
				Integer value = tm.get(key);
				sb.append(key).append("(").append(value).append(")");
			}
			
			//把字元串緩沖區轉換為字元串輸出
			String result = sb.toString();
			System.out.println("result:"+result);
		}
	}
           

Collections 類

public class Collectionsextends Object 是一個針對集合操作的工具類,都是靜态方法。

常見的幾個小方法:

A:public static <T> void sort(List<T> list) 預設情況自然排序
	B:public static <T> int binarySearch(List<?> list,T key) 二分查找
	C:public static <T> T max(Collection<?> coll) 最大值
	D:public static void reverse(List<?> list)翻轉
	E:public static void shuffle(List<?> list)随機置換
           

案例

  • 基礎方法使用
public static void main(String[] args) {
		// 建立集合對象
		List<Integer> list = new ArrayList<Integer>();

		// 添加元素
		list.add(30);
		list.add(20);
		list.add(50);
		list.add(10);
		list.add(40);

		System.out.println("list:" + list);

		// public static <T> void sort(List<T> list):排序 預設情況下是自然順序。
		// Collections.sort(list);
		// System.out.println("list:" + list);
		// [10, 20, 30, 40, 50]

		// public static <T> int binarySearch(List<?> list,T key):二分查找
		// System.out
		// .println("binarySearch:" + Collections.binarySearch(list, 30));
		// System.out.println("binarySearch:"
		// + Collections.binarySearch(list, 300));

		// public static <T> T max(Collection<?> coll):最大值
		// System.out.println("max:"+Collections.max(list));

		// public static void reverse(List<?> list):反轉
		// Collections.reverse(list);
		// System.out.println("list:" + list);
		
		//public static void shuffle(List<?> list):随機置換
		Collections.shuffle(list);
		System.out.println("list:" + list);
	}
           
  • 自定義對象排序
// 建立集合對象
		List<Student> list = new ArrayList<Student>();

		// 建立學生對象
		Student s1 = new Student("林青霞", 27);
		Student s2 = new Student("風清揚", 30);
		Student s3 = new Student("劉曉曲", 28);
		Student s4 = new Student("武鑫", 29);
		Student s5 = new Student("林青霞", 27);

		// 添加元素對象
		list.add(s1);
		list.add(s2);
		list.add(s3);
		list.add(s4);
		list.add(s5);

		// 排序
		// 自然排序
		// Collections.sort(list);
		// 比較器排序
		// 如果同時有自然排序和比較器排序,以比較器排序為主
		Collections.sort(list, new Comparator<Student>() {
			@Override
			public int compare(Student s1, Student s2) {
				int num = s2.getAge() - s1.getAge();
				int num2 = num == 0 ? s1.getName().compareTo(s2.getName())
						: num;
				return num2;
			}
		});

		// 周遊集合
		for (Student s : list) {
			System.out.println(s.getName() + "---" + s.getAge());
		}
           
  • 模拟鬥地主洗牌發牌
import java.util.ArrayList;
	import java.util.Collections;
	
	/*
	 * 模拟鬥地主洗牌和發牌
	 * 
	 * 分析:
	 * 		A:建立一個牌盒
	 * 		B:裝牌
	 * 		C:洗牌
	 * 		D:發牌
	 * 		E:看牌
	 */
	public class PokerDemo {
		public static void main(String[] args) {
			// 建立一個牌盒
			ArrayList<String> array = new ArrayList<String>();
	
			// 裝牌
			// 黑桃A,黑桃2,黑桃3,...黑桃K
			// 紅桃A,...
			// 梅花A,...
			// 方塊A,...
			// 定義一個花色數組
			String[] colors = { "♠", "♥", "♣", "♦" };
			// 定義一個點數數組
			String[] numbers = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10",
					"J", "Q", "K" };
			// 裝牌
			for (String color : colors) {
				for (String number : numbers) {
					array.add(color.concat(number));
				}
			}
			array.add("小王");
			array.add("大王");
	
			// 洗牌
			Collections.shuffle(array);
	
			// System.out.println("array:" + array);
	
			// 發牌
			ArrayList<String> xianglei = new ArrayList<String>();
			ArrayList<String> linQingXia = new ArrayList<String>();
			ArrayList<String> liuYi = new ArrayList<String>();
	
			ArrayList<String> diPai = new ArrayList<String>();
	
			for (int x = 0; x < array.size(); x++) {
				if (x >= array.size() - 3) {
					diPai.add(array.get(x));
				} else if (x % 3 == 0) {
					fengQingYang.add(array.get(x));
				} else if (x % 3 == 1) {
					linQingXia.add(array.get(x));
				} else if (x % 3 == 2) {
					liuYi.add(array.get(x));
				}
			}
	
			// 看牌
			lookPoker("向磊", fengQingYang);
			lookPoker("林青霞", linQingXia);
			lookPoker("劉意", liuYi);
	
			lookPoker("底牌", diPai);
			}
	
			public static void lookPoker(String name, ArrayList<String> array) {
				System.out.print(name + "的牌是:");
				for (String s : array) {
					System.out.print(s + " ");
				}
				System.out.println();
				}
			}
           

如何對發出來的牌進行排序?

圖解:

Java基礎總結篇---Map接口

代碼

/*
	 * 思路:
	 * 		A:建立一個HashMap集合
	 * 		B:建立一個ArrayList集合
	 * 		C:建立花色數組和點數數組
	 * 		D:從0開始往HashMap裡面存儲編号,并存儲對應的牌
	 *        同時往ArrayList裡面存儲編号即可。
	 *      E:洗牌(洗的是編号)
	 *      F:發牌(發的也是編号,為了保證編号是排序的,就建立TreeSet集合接收)
	 *      G:看牌(周遊TreeSet集合,擷取編号,到HashMap集合找對應的牌)
	 */
	public class PokerDemo {
		public static void main(String[] args) {
			// 建立一個HashMap集合
			HashMap<Integer, String> hm = new HashMap<Integer, String>();
	
			// 建立一個ArrayList集合
			ArrayList<Integer> array = new ArrayList<Integer>();
	
			// 建立花色數組和點數數組
			// 定義一個花色數組
			String[] colors = { "♠", "♥", "♣", "♦" };
			// 定義一個點數數組
			String[] numbers = { "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q",
					"K", "A", "2", };
	
			// 從0開始往HashMap裡面存儲編号,并存儲對應的牌,同時往ArrayList裡面存儲編号即可。
			int index = 0;
	
			for (String number : numbers) {
				for (String color : colors) {
					String poker = color.concat(number);
					hm.put(index, poker);
					array.add(index);
					index++;
				}
			}
			hm.put(index, "小王");
			array.add(index);
			index++;
			hm.put(index, "大王");
			array.add(index);
	
			// 洗牌(洗的是編号)
			Collections.shuffle(array);
	
			// 發牌(發的也是編号,為了保證編号是排序的,就建立TreeSet集合接收)
			TreeSet<Integer> fengQingYang = new TreeSet<Integer>();
			TreeSet<Integer> linQingXia = new TreeSet<Integer>();
			TreeSet<Integer> liuYi = new TreeSet<Integer>();
			TreeSet<Integer> diPai = new TreeSet<Integer>();
	
			for (int x = 0; x < array.size(); x++) {
				if (x >= array.size() - 3) {
					diPai.add(array.get(x));
				} else if (x % 3 == 0) {
					fengQingYang.add(array.get(x));
				} else if (x % 3 == 1) {
					linQingXia.add(array.get(x));
				} else if (x % 3 == 2) {
					liuYi.add(array.get(x));
				}
			}
	
			// 看牌(周遊TreeSet集合,擷取編号,到HashMap集合找對應的牌)
			lookPoker("風清揚", fengQingYang, hm);
			lookPoker("林青霞", linQingXia, hm);
			lookPoker("劉意", liuYi, hm);
			lookPoker("底牌", diPai, hm);
		}
	
		// 寫看牌的功能
		public static void lookPoker(String name, TreeSet<Integer> ts,
				HashMap<Integer, String> hm) {
			System.out.print(name + "的牌是:");
			for (Integer key : ts) {
				String value = hm.get(key);
				System.out.print(value + " ");
			}
			System.out.println();
		}
	}
           

總結

HashMap和Hashtable的差別?

  • Hashtable:線程安全,效率低。不允許null鍵和null值
  • HashMap:線程不安全,效率高。允許null鍵和null值

List,Set,Map等接口是否都繼承自Map接口?

  • List,Set不是繼承自Map接口,它們繼承自Collection接口
  • Map接口本身就是一個頂層接口

Collection和Collections的差別

  • Collection 是單列集合的頂層接口,有兩個子接口List和Set
  • Collections 是針對集合進行操作的工具類,可以對集合進行排序和查找等