1. 程式人生 > >java程式設計師從笨鳥到菜鳥之(三十一)集合之TreeMap以及集合巢狀

java程式設計師從笨鳥到菜鳥之(三十一)集合之TreeMap以及集合巢狀

1 TreeMap的兩種遍歷方式

     思路1:鍵值對物件找鍵和值方式

         entrySet()方法:獲取鍵值對物件 ,把鍵和值封裝起來看做一個物件
 1)獲取所有鍵值對物件的集合---entrySet()方法
 2)遍歷鍵值對物件的集合,獲取到每一個鍵值對物件---foreach遍歷
 3)根據鍵值對的得到鍵和值---getKey()和getValue()方法
    思路2:鍵找值方式
 1)獲取所有鍵的集合----keySet()
 2)遍歷鍵的集合,獲取到每一個鍵---foreach遍歷→注意判斷是否非空
 3)根據鍵找值----get(K key)→value
例項1

package demo;

import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

/**
 * @author Orange
 * @version 1.8
 */
// 測試類
public class Test01 {
	public static void main(String[] args) {
		TreeMap<Integer, Student> tm = new TreeMap<Integer, Student>();
		method1(tm);//方式1
		System.out.println("---------------");
		method2(tm);//方式2
		tm.put(1, new Student("小花", 18));
		tm.put(2, new Student("小蘭", 17));
		tm.put(3, new Student("阿迪", 19));
		/**
		 * 思路:將集合轉化為陣列進行遍歷
		 * 錯誤:Map是雙列集合,無法直接轉換成toArray形式
		 * 此種思路pass
		 */
		
	}

	/**
	 * @param tm
	 *     方式2---利用TreeMap本身的keySet得到鍵物件,進而用get(K key)得到值物件
	 */
	private static void method2(TreeMap<Integer, Student> tm) {
		tm.put(1, new Student("小花", 18));
		tm.put(2, new Student("小蘭", 17));
		tm.put(3, new Student("阿迪", 19));
		/*
		 * for(<Integer, Student> s:tm){
			System.out.println(s);
		}
		錯誤:原來想通過這種方式,遍歷元素
		只有通過鍵值對的方法才能遍歷
		*/
		Set<Integer> keySet = tm.keySet();
		/** 
		 * 思路2:-----鍵找值方式
		 * 1)獲取所有鍵的集合----keySet()
		 * 2)遍歷鍵的集合,獲取到每一個鍵---foreach遍歷
		 * 3)根據鍵找值----get(K key)→value
		 * */
		for(Integer integer:keySet){
			System.out.println(integer);
			Student student = tm.get(integer);
			System.out.println("\t"+student.getName()+"---"+student.getAge());
		}
	}

	/**
	 * @param tm
	 *       方式1--利用entrySet()方法去遍歷Map集合中的元素
	 */
	private static void method1(TreeMap<Integer, Student> tm) {
		tm.put(1, new Student("阿花", 18));
		tm.put(2, new Student("阿蘭", 17));
		tm.put(3, new Student("阿迪", 19));
		Set<Entry<Integer, Student>> es = tm.entrySet();//重要!!!
		/**
		 * 思路1:---值對物件找鍵和值方式
		 * entrySet()----鍵值對物件 ,把鍵和值封裝起來看做一個物件
		 * 1)獲取所有鍵值對物件的集合---entrySet()方法
		 * 2)遍歷鍵值對物件的集合,獲取到每一個鍵值對物件---foreach遍歷
		 * 3)根據鍵值對的得到鍵和值---getKey()和getValue()方法
		 */
		for(Entry<Integer, Student> e:es){
			System.out.println(e.getKey());
			Student student = e.getValue();
			/**
			 * 原來錯誤思路:對獲取的鍵值竟然妄想去用foreach遍歷
			 * foreach遍歷:集合或陣列
			 * 哎,差得碼子大!!!
			 */
			System.out.print("\t"+student.getName()+"---"+student.getAge()+"\r");
		}
	}
}
說明:將兩種方法分別封裝到方法裡面

2  HashMap和TreeMap的get()方法的應用

例項2

package demo;

import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;

/**
 * @author Orange
 * @version 1.8
 */

public class Test02 {
	/**
	 * 
	 * 練習1:需求:統計字串中每個字元出現的次數----HashMap
	 * "aababcabcdabcde",獲取字串中每一個字母出現的次數要求結果:a(5)b(4)c(3)d(2)e(1)
	 * 練習2:需求:將字串中的字元按照先後a-z的方式進行排序----TreeMap
	 * 如果bdadabcc-----結果:a(2)b(2)c(2)d(2)
	 */
	/**
	 * 分析:分析字串,再觀察字串要求的結果,裡面為每個字出現的次數
	 * 大方法思路:建立一個StringBuilder的物件利用append()方法拼接字元'('和')'和次數
	 * 用集合的觀點看世界。。。
	 * 通過觀察有點像鍵值對(除了'('和')'),既然決定用鍵值對,關鍵是如何如何統計次數
	 * 技巧:通過get()方法的返回值對字元進行計數
	 */
	//1---建立鍵盤錄入物件,輸入字串----字元字串
	@SuppressWarnings("resource")
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("請輸入字串:");
		String reStr = sc.nextLine();
		//由於是要對字串中的字元進行計數,轉化成字元陣列
		char[] charArray = reStr.toCharArray();
		//建立一個集合容器儲存鍵值對物件---字元和對應次數
		exercise1(charArray);//練習1
		exercise2(charArray);//練習2
	}

	/**
	 * @param charArray
	 */
	private static void exercise2(char[] charArray) {
		//由於要進行排序--TreeMap集合
		TreeMap<Character, Integer> tm = new TreeMap<Character,Integer>();
		if(charArray!= null){
			for(char c:charArray){
				//用集合的get()方法判斷集合中是否已經有該字元物件
				if(tm.get(c)==null){
					tm.put(c, 1);//如果為null,表示還沒有此值物件,將value設定為1
				}else{
					//如果不為null,表示集合中已經有該值物件對應的鍵物件,只需要對值物件做改變
					Integer value = tm.get(c);//得到當前鍵的值物件,重新賦值
					tm.put(c, ++value);
				}
			}
		}
		//好了,關鍵的地方已經弄的差不多了,該建立字串緩衝區物件了
		//建立StringBuilder的物件
		StringBuilder sb = new StringBuilder();
		//需要對HashMap集合中的鍵和值遍歷出來用append()拼接
		//首先得到"鍵值對"對應的鍵和值
		Set<Entry<Character, Integer>> es = tm.entrySet();
		if(es!=null){//foreach缺點:---所以必須進行非空判斷
			for(Entry<Character, Integer> s:es){
				//得到鍵值對物件的鍵
				Character key = s.getKey();
				//得到鍵對應的值
				Integer value = s.getValue();
				//下面就是拼接了
				sb.append(key).append("(").append(value).append(")");
			}
		}
		System.out.println(sb);
	}

/**
 * @param charArray
 */
private static void exercise1(char[] charArray) {
	HashMap<Character, Integer> hm = new HashMap<Character,Integer>();
	//對字元陣列的字元進行遍歷---foreach
	if(charArray!= null){
		for(char c:charArray){
			//用集合的get()方法判斷集合中是否已經有該字元物件
			if(hm.get(c)==null){
				hm.put(c, 1);//如果為null,表示還沒有此值物件,將value設定為1
			}else{
				//如果不為null,表示集合中已經有該值物件對應的鍵物件,只需要對值物件做改變
				Integer value = hm.get(c);
				hm.put(c, ++value);
			}
		}
	}
	
	
	//好了,關鍵的地方已經弄的差不多了,該建立字串緩衝區物件了
	//建立StringBuilder的物件
	StringBuilder sb = new StringBuilder();
	//需要對HashMap集合中的鍵和值遍歷出來用append()拼接
	//首先得到"鍵值對"對應的鍵和值
	Set<Entry<Character, Integer>> es = hm.entrySet();
	if(es!=null){//foreach缺點:---所以必須進行非空判斷
		for(Entry<Character, Integer> s:es){
			//得到鍵值對物件的鍵
			Character key = s.getKey();
			//得到鍵對應的值
			Integer value = s.getValue();
			//下面就是拼接了
			sb.append(key).append("(").append(value).append(")");
		}
	}
	System.out.println(sb);
 }
}
說明:程式碼的冗餘度較高,為方便說明,不再簡寫

3  集合巢狀

 3.1集合巢狀之HashMap巢狀ArrayList-----HashMap儲存的是ArrayList型別元素

 以如下的方式在控制檯列印:
       巨星
               林正英18
               李小龍24
一線明星
               馮紹峰20
               黃海波24

練習1  Student類

package demo;

/**
 * @author Orange
 * @version 1.8
 */
public class Student {
	private String name;
	private int age;

	public Student() {
		super();
		
	}

	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

}

測試類

package demo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;

/**
 * @author Orange
 * @version 1.8
 */
public class Demo03 {
	/*	
	分析:HashMap鍵值對儲存元素	
	思考:由於java的Map類中允許"值物件"也是Map型別的
	做法:可以將"林正英---18"以鍵值對的形式來表示,此時不需要Student類了,感興趣可以自己嘗試一下		
	*/
	public static void main(String[] args) {
		//建立兩個ArrayList----容器
		ArrayList<Student> al1 = new ArrayList<Student>();
		//儲存元素,匿名內部類
		al1.add( new Student("林正英",18));
		al1.add( new Student("李小龍",24));
		
		ArrayList<Student> al2 = new ArrayList<Student>();
		//儲存元素,匿名內部類形式
		al2.add( new Student("馮紹峰",20));
		al2.add( new Student("黃海波",24));
		//將集合元素新增到大集合中
		HashMap<String, ArrayList<Student>> hashMap = new HashMap<>();//泛型推斷
		hashMap.put("巨星", al1);//al1的物件的型別
		hashMap.put("一線明星", al2);
		//老規矩:遍歷先做非空判斷
		Set<Entry<String, ArrayList<Student>>> es = hashMap.entrySet();//鍵值對物件
		if(es!=null){
			for(Entry<String, ArrayList<Student>> s:es){
				String key = s.getKey();//獲取
				System.out.println(key);
				ArrayList<Student> value = s.getValue();//獲取
				for(Student student:value){//遍歷
					System.out.println("\t"+student.getName()+"\t"+student.getName());
				}
			}
		}
		
	}
	
}

3.2  HashMap巢狀HashMap

   以上述為例,仍列印上面的內容

練習2

package demo;

import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;

/**
 * @author Orange
 * @version 1.8
 */
public class Demo4 {
	/**
	 * HashMap巢狀HashMap
	 */
	public static void main(String[] args) {
		//建立兩個小集合---儲存元素
		HashMap<String, Integer> hm1 = new HashMap<String,Integer>();
		hm1.put("林正英",18);
		hm1.put("李小龍",24);
		HashMap<String, Integer> hm2 = new HashMap<String,Integer>();
		hm2.put("馮紹峰",20);
		hm2.put("黃海波",24);
		//建立大集合
		HashMap<String, HashMap<String, Integer>> hashMap = new HashMap<>();
		hashMap.put("巨星", hm1);
		hashMap.put("一線明星", hm2);
		if(hashMap!=null){//其實沒必要---hashMap鍵值都可以是null
			Set<String> keySet = hashMap.keySet();//得到鍵集合
			if(keySet!=null){                     //非空判斷
				for(String s:keySet){         //遍歷鍵集合
					System.out.println(s);
					//根據鍵獲取值
					HashMap<String, Integer> hashMap2 = hashMap.get(s);
					    Set<Entry<String, Integer>> entrySet = hashMap2.entrySet();
					    //對裡層的hashMap做遍歷,其實還是得做非空判斷
						for(Entry<String, Integer> s1:entrySet){
							System.out.println("\t"+s1.getKey()+"---"+s1.getValue());
					}
				}
			}
		}
	}
	
}
說明:Map的值物件還可以是Map型別,但是鍵物件不可以111

3.3 ArrayList之HashMap

列印如下內容:

     周瑜---小喬
     呂布---貂蟬

     郭靖---黃蓉
     楊過---小龍女

     令狐沖---任盈盈
     林平之---嶽靈珊

練習3

package demo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;

/**
 * @author Orange
 * @version 1.8
 */
public class Demo05 {
	public static void main(String[] args) {
		HashMap<String, String> hashMap1 = new HashMap<String, String>();
		hashMap1.put("周瑜", "貂蟬");
		hashMap1.put("楊過", "楊玉環");
		HashMap<String, String> hashMap2 = new HashMap<String, String>();
		hashMap2.put("郭靖", "楊桃");
		hashMap2.put("呂布", "鳳姐");
		HashMap<String, String> hashMap3 = new HashMap<String, String>();
		hashMap3.put("令狐沖", "高圓圓");
		hashMap3.put("林平之", "白晶晶");
		ArrayList<HashMap<String, String>> arrayList = new ArrayList<>();
		arrayList.add(hashMap1);
		arrayList.add(hashMap2);
		arrayList.add(hashMap3);
		if(arrayList!=null){//非空判斷
			for(HashMap<String, String> hm:arrayList){//對ArrayList元素遍歷
				Set<Entry<String, String>> eS = hm.entrySet();//有兩個鍵值對物件
				for(Entry<String, String> se:eS){//得到每個鍵值對物件的鍵和值
					System.out.println(se.getKey()+"---"+se.getValue());
				}
				System.out.println();
			}
		}
	}
}
未完待續......