Set集合对应的HashSet类和TreeSet类的重复值

关于HashSet类,这是我刷leetcode时看了官方的一个代码写法产生的疑问,在网上没有搜寻到答案,最后在API找到的答案:

     为什么在网上找不到答案呢?显示的都是说HasSet不能存储重复的元素(或许我的理解有问题),越看越迷糊,最后突然想到去看API才找到正解!----->> 地址  !=  数值(内容),下面统一用”内容“代替我们常说的”数值“ !!!!

HashSet这里的重复值并不是指“内容相同”的两个变量,而是两个变量的“地址”是否指向同一块,地址相同的才是“重复值”。但是,在基本数据类型中 int,double,float 等基本类型,这些类型”相同的内容“会指向同一块地址,但是自定义的类所实例化(new)的不同对象会指向不同的地址,尽管“内容相同”,但在HashSet 类中不会被判为重复值,看下面代码更清晰

基本数据类型以 int 为例:

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Scanner sc =new Scanner(System.in) ;
	    int a = 3 ;
	    int b = 3 ;
	    System.out.println("整数类型:");
	    System.out.println("a的地址: " + System.identityHashCode(a));
		System.out.println("b的地址: " + System.identityHashCode(b));
		
		Set<Integer> intSet = new HashSet<Integer>() ;
		System.out.print("输入值:");
		for(int i=0; i<5; i++){
			intSet.add(sc.nextInt()) ;
		}
		Iterator<Integer> intIt = intSet.iterator() ;
		while(intIt.hasNext()){
			System.out.print(intIt.next() + " ");
		}
		
		sc.close();
	  
	}
}

运行结果:

int等基本数据类型的”相同内容“指向的地址相同,”相同内容“都被去掉了

String是属于引用类型,直接赋予”相同字符串“给不同的变量,它们指向的地址是相同的,但是用“相同内容”new String()创建的不同变量又会指向不同的地址,而自定义的类就像new String(),实例化(new)”相同内容“给不同变量,它们指向的地址是不同的。

总的来说,就是每new 一个对象都会为对应的变量开辟一个独有的地址

看下面代码示例:


import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;

//自定义类
class ListNode  {
     int val;
     ListNode(int x) {
         val = x;
     }
 }

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Scanner sc =new Scanner(System.in) ;
		//new  String类型
		System.out.println("new String类型:");
		String sk = new String("kkk") ;
		String sg = new String("kkk") ;
		System.out.println("sk的地址: " + System.identityHashCode(sk));
		System.out.println("sg的地址: " + System.identityHashCode(sg));
		
		//直接赋值字符串
		String s1 ="kkk" ;
		String s2 ="kkk" ;
		System.out.println("String类型:");
		//分别 输出变量s1,s2 地址
		System.out.println("s1的地址: " + System.identityHashCode(s1));
		System.out.println("s2的地址: " + System.identityHashCode(s2));
		
		//建立HashSet表
		Set<String> strSet = new HashSet<String>() ;
		
		//输入值验证
		for(int i=0; i<5; i++){
			strSet.add(sc.next()) ;
		}
		
		//HashSet的迭代器---输出
		Iterator<String> str = strSet.iterator() ;
		while(str.hasNext()){
			System.out.print(str.next() + " ");
		}
		
		
		System.out.println();
		System.out.println("-----------------------------------------");
		System.out.println();
		
//		自定义类ListNode
		ListNode n1 = new ListNode(1) ;
		ListNode n2 = new ListNode(1) ;
		System.out.println("自定义类ListNode:");
		//输出n1,n2 地址
		System.out.println("n1= " + n1 + "  n1的地址: " + System.identityHashCode(n1));
		System.out.println("n2= " + n2 + "  n2的地址: " + System.identityHashCode(n2));
		
		//创建HashSet表
		Set<ListNode> nSet = new HashSet<ListNode>() ;
		
		//随便输入几个值验证
		for(int i=0; i<5; i++){
			nSet.add(new ListNode(sc.nextInt())) ;
		}
		
		//HashSet的迭代器---输出
		Iterator<ListNode> nd = nSet.iterator() ;
		while(nd.hasNext()){
			System.out.print(nd.next().val + " ");
		}
		
		sc.close();
	}
}

运行结果:

通过运行的结果对比,想必很直观了,“相同内容”的new String()的不同变量指向的地址不同,这里就没用列表演示了(类似下面的ListNode类),可以自行去试一下。而String的直接赋值”相同内容“会指向同一块地址,所以会被去掉,而自定义的ListNode类,尽管”内容相同“,但它们指向的地址不同,所以不会被当成”重复内容“去掉。

另外,HashSet类不保证元素的顺序,如果要求元素顺序的,这个就不适用了

TreeSet类就比较直接了,它所指的重复值就是”相同内容“,与数据类型、地址无关

下面代码示例:


import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;


//自定义类需要实现Comparable<>接口,才能使用TreeSet类,否则运行会报错
class ListNode implements Comparable<ListNode>{
     int val;
     ListNode(int x) {
         val = x;
     }
	@Override
	public int compareTo(ListNode arg) {
		// TODO Auto-generated method stub
		if(this.val > arg.val)
			return 1 ;
		else if(this.val < arg.val)
			return -1 ;
		else
			return 0;
	}
     
     
 }

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Scanner sc =new Scanner(System.in) ;
		
		//实现int型TreeSet类
		Set<Integer> intSet = new TreeSet<Integer>() ;
		System.out.println("int型:");
		for(int i=0; i<6; i++){
			intSet.add(sc.nextInt()) ;
		}
		for(int y: intSet){
			System.out.print(y + " ");
		}
		
		
		System.out.println();
		System.out.println();
		System.out.println();
		
		
		
		//实现自定义类型TreeSet类
		Set<ListNode> nSet = new TreeSet<ListNode>() ;
		System.out.println("自定义类型:");
		for(int j=0; j<6; j++){
			nSet.add(new ListNode(sc.nextInt())) ;
		}
		for(ListNode x: nSet){
			System.out.print(x.val + " ");
		}
		sc.close();
	}
}

运行结果:

从运行结果可知,TreeSet类会去掉“相同的内容”,也就是我们平常说的“数值”,最后升序输出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值