TreeSet集合

Set集合

 Set接口:Set集合繼承自Collection集合

      Set:底層數據結構是一個哈希表,能保證元素是唯一的,元素不重複!  它通過它的子實現了HashSet集合去實例化,HashSet集合底層是HashMap集合的實例!  

 例. 需求:Set集合存儲字符串元素並遍歷

public class SetDemo {
	
	public static void main(String[] args) {
		
		//創建Set集合對象
		Set<String> set = new HashSet<String>() ;
		
		//添加元素
		set.add("hello");
		set.add("java") ;
		set.add("java") ;
		set.add("world") ;
		set.add("world") ;
		set.add("world") ;
		
		//增強for遍歷
		for(String s :set){
			System.out.println(s);
		}
	}
}


List集合和Set集合的區別?


    Set:元素是唯一的,無序性(存儲和取出不一致)

    List:元素可以重複,有序性(存儲和取出一致)

Set集合的子實現類:

1)HashSet:

實現Set接口,依靠Hashtable,他不保證迭代的順序,特別的是,它不能保證數據保持不變,隨着時間的推移。這個集合可以包含null值。存儲結構實際爲HashMap


HashSet集合的add()方法,底層是依賴於雙列集合HashMap<K,V>的put(K key,V value)來實現的
   put(K key,V value):
    底層又依賴於HashCode()和equals()方法,傳遞添加元素的時候,首先判斷的是
  每一個元素對應的HashCode值是否一樣,如果HashCode值一樣,還比較他們的equals()方法,由於現在集合存儲的是String類型,String類型本身重寫
  了equals()方法,所以,默認比較的是內容是否相同,如果內容相同,這裏最終返回的就是第一次存儲的那個元素,由這兩個方法保證元素唯一性!

例:使用HashSet集合存儲自定義對象並遍歷

import java.util.HashSet;

public class HashSetDemo {
	
	public static void main(String[] args) {
		
		//創建一個HashSet集合對象
		HashSet<Student> hs = new HashSet<Student>() ;
		
		//創建學生對象
		Student s1 = new Student("高圓圓", 27) ;
		Student s2 = new Student("張三", 25) ;
		Student s3 = new Student("唐嫣", 26) ;
		Student s4 = new Student("鄧超", 29) ;
		Student s5 = new Student("胡歌", 23) ;
		Student s6 = new Student("高圓圓", 27) ;
		
		//給集合中添加學生對象
		hs.add(s1) ;
		hs.add(s2) ;
		hs.add(s3) ;
		hs.add(s4) ;
		hs.add(s5) ;
		hs.add(s6) ;
		
		//增強for遍歷
		for(Student s : hs){
			System.out.println(s.getName()+"---"+s.getAge());
		}
		/**
		 * "高圓圓---27" 重複出現是因爲現在是自定義對象:在當前自定義對象的類中沒有重寫兩個方法
                 * hashCode和equals()方法;HashSet底層是依賴於這兩個實現來保證元素的唯一性!
                 * 
		 * */
	}
}

HashSet的子類LinkedHashSet集合:
         由哈希表保證元素的唯一性
         由鏈接列表來保證元素的有序性!

        具有可預知迭代順序的Set接口的哈希表和鏈接列表實現。此實現與HashSet的不同之處在於,後者維護着一個運行於所有條目的雙重鏈接列表。此鏈接列表定義了迭代順序,該迭代順序可爲插入順序或是訪問順序。

public class LinkedHashSetDemo {
	
	public static void main(String[] args) {
		
		//創建LinkedHashSet集合對象
		LinkedHashSet<String> link = new LinkedHashSet<String>();
		
		//給集合中添加元素
		link.add("hello") ;
		link.add("world") ;
		link.add("world") ;
		link.add("Java") ;
		link.add("Java") ;
		link.add("JavaWeb") ;
		link.add("JavaWeb") ;
		
		//遍歷集合
		for(String s: link){
			System.out.println(s);//元素唯一併且有序
		}
	}
}


2) TreeSet集合

先了解一下紅黑樹

紅黑樹是一種自平衡的二叉查找樹 ,那麼二叉查找樹(BST)具備什麼特性呢?


1.左子樹上所有結點的值均小於或等於它的根結點的值。
2.右子樹上所有結點的值均大於或等於它的根結點的值。
3.左、右子樹也分別爲二叉排序樹。




這種方式是二分查找的思想,當需要查找10這個元素時,查找的次數就是樹的高度,但是二叉查找樹也存在缺陷,比如


所以紅黑樹應運而生關於紅黑樹的規則:

1.節點是紅色或黑色。
2.根節點是黑色。
3.每個葉子節點都是黑色的空節點(NIL節點)。
4 每個紅色節點的兩個子節點都是黑色。(從每個葉子到根的所有路徑上不能有兩個連續的紅色節點)
5.從任一節點到其每個葉子的所有路徑都包含相同數目的黑色節點。

下圖中這棵樹,就是一顆典型的紅黑樹:



紅黑樹可以通過變色 ,旋轉來調整被打破的規則

TreeSet集合底層是依賴於TreeMap的實例,而TreeMap<K,V>是依賴於紅黑樹結構實現的

分兩種:

   自然排序:
   比較器排序
  這種排序的使用取決於開發者是用什麼樣的構造方法

public class TreeSetDemo {
	
	public static void main(String[] args){
		
//		throw new IOException();
		//創建TreeSet集合對象
		//構造方法:
		//public TreeSet():無參構造:根據其元素的自然順序進行排序
		//publict TreeSet(Comparaptr<E> com)
		TreeSet<Integer> ts = new TreeSet<Integer>();//
		
		//添加元素
		//20,18,23,22,17,24,19,18,24
		ts.add(20);// Integer i = Integer.valueOf(20) ;
		ts.add(18) ;
		ts.add(23) ;
		ts.add(22) ;
		ts.add(17) ;
		ts.add(24) ;
		ts.add(19) ;
		ts.add(18) ;
		ts.add(24) ;
		
		
		//遍歷這些元素
		//增強for遍歷
		for(Integer i : ts){
			System.out.print(i+ " ");//17 18 19 20 22 23 24 :唯一併且排序:自然排序(升序排序)
		}
	}
}

TreeSet集合存儲自定義對象並遍歷

對於TreeSet集合存儲自定義對象必須實現一個接口:compareable接口


Student類中實現了compareable接口,重寫了comapreTo()方法,裏面的邏輯是一個排序條件:

public class TreeSetDemo2 {
	
	public static void main(String[] args) {
		
		//創建TreeSet集合對象
		TreeSet<Student> ts = new TreeSet<Student>() ;//
		
		//創建學生對象
		Student s1 = new Student("linqingxia", 28) ;
		Student s2 = new Student("fengqingy", 28) ;
		Student s3 = new Student("gaoyuanyuan", 27) ;
		Student s4 = new Student("liushishi", 26) ;
		Student s5 = new Student("wanglihong", 29) ;
		Student s6 = new Student("zhangguorong", 30) ;
		Student s7 = new Student("zhangguorong", 30) ;
		
		ts.add(s1);
		ts.add(s2);
		ts.add(s3);
		ts.add(s4);
		ts.add(s5);
		ts.add(s6);
		ts.add(s7);
		
		//遍歷
		for(Student s : ts){
			System.out.println(s.getName()+"---"+s.getAge());
		}
	}	
}

需求:按照學生姓名長度從小到大進行排序
 
  元素唯一性:取決返回值是否爲0
  要使用TreeSet集合的比較器排序:
   依賴於構造方法:
   public TreeSet(Comparator<E> comparator)
  
   兩種方式實現比較器排序:
  Comparator接口作爲形式參數進行傳遞,需要該接口的子實現類對象

方式1:自定義一個類,類實現Comparator接口,作爲子實現類
方式2:可以使用接口的匿名內部類來實現(開發中,由於減少代碼書寫量,不需要自定義接口的子實現類,直接這種格式! )

public class TreeSetDemo {
	
	public static void main(String[] args) {
		//創建TreeSet集合使用比較器進行給元素進行排序
		//public TreeSet(Comparator<E> comparator):有參構造	
		//使用接口的匿名內部類來實現
		/**
		 * 格式
		 * new 接口名或者類名(){
		 * 		重寫方法() ;
		 * } 
		 */
//		TreeSet<Student> ts = new TreeSet<Student>(new MyComparator()) ;
		TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {

			@Override
			public int compare(Student s1, Student s2) {
//				return 0;
				
				int num = s1.getName().length() - s2.getName().length() ;
				//次要條件:姓名長度一樣,還要比較姓名的內容是否一樣
				int num2 = num==0 ? s1.getName().compareTo(s2.getName()): num ;
				
				//姓名長度和內容都一樣,還需比較兩個人的年齡是否一樣
				int num3 = num2 ==0 ? s1.getAge() - s2.getAge() : num2 ;
				
				return num3 ;
			}
			
		}) ;
		
		
		//創建學生對象
		Student s1 = new Student("gaoyuanyan", 27) ;
		Student s2 = new Student("liushishi", 22);
		Student s3 = new Student("fengqingy", 23) ;
		Student s4 = new Student("wuqilong", 35) ;
		Student s5 = new Student("gaoyuanyuan",27) ;
		Student s6 = new Student("zhangguorong",29) ;
		Student s7 = new Student("gaoyuanyuan",26) ;
		
		
		//添加元素
		ts.add(s1) ;
		ts.add(s2) ;
		ts.add(s3) ;
		ts.add(s4) ;
		ts.add(s5) ;
		ts.add(s6) ;
		ts.add(s7) ;
		
		//增強for遍歷
		for(Student s : ts){
			System.out.println(s.getName()+"----"+s.getAge());
		}
	}
}
鍵盤錄入五個農藥英雄比較他們的各自特點及總體性能
public class TreeSetTest {

	public static void main(String[] args) {
		//創建TreeSet集合
		TreeSet<Hreo> ts = new TreeSet<Hreo>(new Comparator< Hreo>() {

			@Override
			public int compare(Hreo h1, Hreo h2) {
				//條件
				int num = h2.getSum() - h1.getSum();
				int num2 = num == 0?h1.getLive()-h2.getLive():num;
				int num3 = num == 0?h1.getAttack()-h2.getAttack():num2;
				int num4 = num == 0?h1.getSkill()-h2.getSkill():num3;
				int num5 = num == 0?h2.getDifficult()-h1.getDifficult():num4;
				return num5;
			}
			
		});
		System.out.println("錄入英雄信息開始:");
		//創建鍵盤錄入並使用String類型接受
		for(int x =1;x <= 5;x++) {
			Scanner sc = new Scanner(System.in);
			System.out.println("請輸入第"+x+"個英雄的姓名:");
			String name = sc.nextLine();
			System.out.println("請輸入第"+x+"個英雄的生存值:");
			String liveString = sc.nextLine();
			System.out.println("請輸入第"+x+"個英雄的技能值:");
			String skillString = sc.nextLine();
			System.out.println("請輸入第"+x+"個英雄的難度值:");
			String difficultString = sc.nextLine();
			System.out.println("請輸入第"+x+"個英雄的攻擊值:");
			String attackString = sc.nextLine();
			//創建英雄對象
			Hreo  h = new Hreo();
			//把英雄信息傳進去
			h.setName(name);
			//將String類型轉爲int類型
			h.setLive(Integer.parseInt(liveString));
			h.setSkill(Integer.parseInt(skillString));
			h.setDifficult(Integer.parseInt(difficultString));
			h.setAttack(Integer.parseInt(attackString));
			
			ts.add(h);
			System.out.println("英雄信息錄入完畢!");
			System.out.println("英雄性能從高到低排列如下:");
			System.out.println("姓名\t生存\t技能\t難度\t攻擊");
			//增強for遍歷
			for(Hreo h1:ts) {
				System.out.println(h1.getName() + "\t" + h1.getLive() + "\t" + h1.getSkill() + "\t" + 
						h1.getDifficult() + "\t" + h1.getAttack());
					}
			}
			
	}
}

獲取10個1-20之間的隨機數,要求不能重複

public class Test {
	
	public static void main(String[] args) {
		
		//1)創建一個隨機數生成器
		Random r = new Random();
		
		//2)創建ArrayList集合,類型Integer
		ArrayList<Integer> array = new ArrayList<Integer>() ;
		
		//3)定義統計遍歷
		int count = 0 ;
		
		//4)循環判斷
		while(count <10){
			
			//通過隨機數生成器獲取:1-20之間的隨機數public int nextInt(int n):生成隨機數的範圍:[0,n)
			int number = r.nextInt(20) +1;
			
			//有隨機數了,還需要判斷集合中是否包含這些隨機數
			if(!array.contains(number)){
				//如果不包含,才添加到集合中
				array.add(number) ;
				count ++ ;
			}
		}
		
		
		//遍歷集合:增強for
		for(Integer i : array){
			System.out.println(i);
		}
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章