java(八)Set集合、HashSet、TreeSet

集合 的体系:
------------| Collection 单例集合的根接口
----------------| List  如果是实现了List接口的集合类,具备的特点: 有序,可重复。 
--------------------| ArrayList  ArrayList 底层是维护了一个Object数组实现的。 特点: 查询速度快,增删慢。
--------------------| LinkedList LinkedList 底层是使用了链表数据结构实现的, 特点: 查询速度慢,增删快。
--------------------| Vector(了解即可)  底层也是维护了一个Object的数组实现的,实现与ArrayList是一样的,但是Vector是线程安全的,操作效率低。

----------------| Set  如果是实现了Set接口的集合类,具备的特点: 无序,不可重复
                            ---| HashSet  线程不安全,存取速度快。底层是以hash表实现的。

                            ---| TreeSet  红-黑树的数据结构,默认对元素进行自然排序(String)。如果在比较的时候两个对象返回值为0,那么元素重复。

无序: 添加元素 的顺序与元素出来的顺序是不一致 的。

1.   HashSet  

hashSet的实现原理:
往Haset添加元素的时候,HashSet会先调用元素的hashCode方法得到元素的哈希值 ,
然后通过元素 的哈希值经过移位等运算,就可以算出该元素在哈希表中 的存储位置。
情况1: 如果算出元素存储的位置目前没有任何元素存储,那么该元素可以直接存储到该位置上。

情况2: 如果算出该元素的存储位置目前已经存在有其他的元素了,那么会调用该元素的equals方法与该位置的元素再比较一次,

     如果equals返回的是true,那么该元素与这个位置上的元素就视为重复元素,不允许添加,如果equals方法返回的是false,那么该元素运行 添加。

  hashCode
public class test_1{
	   public static void main(String args[])  {
		 
		 String str1 = "hello";
		 String str2 =  new String("hello");
		 System.out.println("两个是同一个对象吗?  " + (str1 == str2));
		 System.out.println("str1的hashCode: " + str1.hashCode());  
		 System.out.println("str1的hashCode: " + str2.hashCode());  
		 //   hashCode默认情况下表示的是内存地址,string 类已经重写了object的hashCode方法	 
	   }  
}

运行结果:

两个是同一个对象吗?  false
str1的hashCode: 99162322
str1的hashCode: 99162322

hashCode 的源码是:

/* 源码     注意: 如果两个字符串的内容一致,那么返回的hashCode 码也会一致。
 * public static int hashCode(byte[] value) {
    int h = 0;
    for (byte v : value) {
        h = 31 * h + (v & 0xff);
    }
    return h;
}*/


   实例: 接受键盘录入用户名与密码,如果用户名与密码已经存在集合中,那么就是视为重复元素,不允许添加到HashSet中。 

使用HashSet存储自定义对象,并尝试添加重复对象(对象的重复的判定)

import java.util.HashSet;
import java.util.Scanner;

 class People{
	String username;
	String password;
	
	public  People(String username, String password) {	
		super();
		this.username = username;
		this.password = password;
	}	
	@Override
	public String toString() {	    //  重写  String
		return "用户名:  " + this.username + " 密码:  " + this.password;
	}
	@Override
	public boolean equals(Object obj) {     //   重写  equals
		People p1 = (People)obj;
		return this.username.equals(p1.username) && this.password.equals(p1.password);
	}
	@Override
	public int hashCode() {		//    重写  hashCode
		return username.hashCode() + password.hashCode();
	} 	
}

public class test_1{
	   public static void main(String args[])  {
		Scanner scanner = new Scanner(System.in);
		HashSet set = new HashSet();
		
		while (true) {
		System.out.println("请输入用户名");
	        String username = scanner.next();
	        System.out.println("请输入密码: ");
		String password =  scanner.next(); 
		
		// 创建一个对象
		People p1 = new People(username, password);
		if(set.add(p1)) {
			System.out.println("注册成功");
			System.out.println(set);			
		}else {
			System.out.println("注册失败");
		}			
	  }
   }  
}

运行结果: 

请输入用户名
fzx
请输入密码: 
000
注册成功
[用户名:  fzx 密码:  000]
请输入用户名
fzx
请输入密码: 
000
注册失败
请输入用户名

2.  TreeSet  

红黑树算法的规则: 左小右大。
既然TreeSet可以自然排序,那么TreeSet必定是有排序规则的。
  1:   让存入的元素自定义比较规则。
  2:   给TreeSet指定排序规则。
           方式一:元素自身具备比较性
      元素自身具备比较性,需要元素实现Comparable接口,重写compareTo方法,也就是让元素自身具备比较性,这种方式叫做元素的自然排序也叫做默认排序。
          
        方式二:容器具备比较性,也就是自定义比较器。
     当元素自身不具备比较性,或者自身具备的比较性不是所需要的。那么此时可以让容器自身具备。需要定义一个类实现接口Comparator,重写compare方法,并将该接口的子类实例对象作为参数传递给TreeMap集合的构造方法。
注意:当Comparable比较方式和Comparator比较方式同时存在时,以Comparator的比较方式为主;

///////  实例: 

import java.util.Comparator;
import java.util.TreeSet;

class emp implements Comparable{	
	//class emp {	
		int id;
		String name;
		int  salary;
		public  emp(int id, String name, int salary) {
			this.id = id;
			this.name = name;
			this.salary = salary;		
		}
		@Override
		public String toString() {		
			return "  {编号: " + this.id + " 姓名: " + this.name + " 薪水: " + this.salary + "} ";
		}
		@Override
		// 返回:负整数、零或正整数,根据此对象是小于、等于还是大于指定对象
		public int compareTo(Object obj) {
			emp e = (emp) obj;		
			System.out.println(this.name + "比较" + e.name);			
			return  this.salary - e.salary;
		}	
	}

	class Mycomparator implements Comparator{
		@Override
		public int compare(Object obj1, Object obj2) {
			emp e1 = (emp)obj1;
			emp e2 = (emp)obj2;
			return e1.id-e2.id;
		}	
	}

	public class test_1{
		   public static void main(String args[])  { 
		  
		  Mycomparator compare = new Mycomparator();
		  //  创建TreeSet对象,传入比较器;
		  TreeSet tree = new TreeSet(compare);
		  
	//	 TreeSet tree = new TreeSet();	   
	    /*  tree.add(1);
	      tree.add(7);
	      tree.add(4);*/
		  
	      /*tree.add('b');
	      tree.add('a');
	      tree.add('c');*/
	      tree.add(new emp(3, "付祖贤", 10000));
	      tree.add(new emp(1, "女侠", 15000));
	      tree.add(new emp(2, "仙女", 20000));
	      tree.add(new emp(4, "女神经", 20000));
	        
	      System.out.println(tree);
	   }  
	}

让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo 方法。运行结果: 

女神经比较女侠
女神经比较仙女
[  {编号: 3 姓名: 付祖贤 薪水: 10000} ,   {编号: 1 姓名: 女侠 薪水: 15000} ,   {编号: 2 姓名: 仙女 薪水: 20000} ]

容器自身具备比较性,定义一个类实现Comparator 接口,覆盖compare方法。使用自定义的比较器:

[  {编号: 1 姓名: 女侠 薪水: 15000} ,   {编号: 2 姓名: 仙女 薪水: 20000} ,   {编号: 3 姓名: 付祖贤 薪水: 10000} ,   {编号: 4 姓名: 女神经 薪水: 20000} ]
//////   TreeSet练习一:
import java.util.TreeSet; 
/* * 
 * TreeSet 是可以对字符串进行排序的,因为字符串已经实现了Comparable接口
 * 
 * 字符串比较规则:
 *    1. 找到对应不同的字符,比较的就是对应位置上的字符;
 *    2. 找不到对应不同的字符,比较字符串的长度;
*/
public class test_1{
	   public static void main(String args[])  { 
	     TreeSet tree = new TreeSet();
	     tree.add("aacccccccc");
	     tree.add("ab");
	     tree.add("aw");
		 System.out.println(tree);     
   }  
}

运行结果:

[aacccccccc, ab, aw]
TreeSet练习二 :   将字符串中的数值进行排序。
例如String str="8 10 15 5 2 7";    2,5,7,8,10,15
  使用 TreeSet完成。 
          思路: 1,将字符串切割。
                   2,可以将这些对象存入TreeSet集合。        因为TreeSet自身具备排序功能
public class test_1{
	   public static void main(String args[])  { 
	      
		 String num = "10 12 8 3 16 20 42";
		 String[] num2 = num.split(" ");
		 TreeSet tree = new TreeSet();
		 for(int i=0; i<num2.length; i++) {	
		//	 tree.add(num2[i]); 
			//  字符串转int类型数据是需要使用  Integer.parseInt
			 tree.add(Integer.parseInt(num2[i]));		 
		 }
		System.out.println(tree);   	   
   }  
}

运行结果:

[3, 8, 10, 12, 16, 20, 42]


猜你喜欢

转载自blog.csdn.net/image_fzx/article/details/80246901