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);
		}
	}
}


猜你喜欢

转载自blog.csdn.net/dreamer_96/article/details/78526107