HashSet TreeSet 和 equals、hashCode、comparable接口之间关联

HashSet HashMap HashTable:内部采用哈希表实现

TreeSet TreeMap:排序,利用 compareTo或者comparator比较功能实现

 问题思考:在HashSet添加 new BigDecimal(“1.0”)和new BigDecimal(“1.00”)两个都添加!而在TreeSet添加 new BigDecimal(“1.0”)和new BigDecimal(“1.00”) 却只添加一个?这是为什么?

HashSet判断两个元素是否相等,HashSet判断两个元素是否相同是通过equals来实现的,但是如果全部扫描一遍则时间复杂度为O(n),为了提高效率采用hash表实现,而hash表查找是根据hashcode比较来实现的。所以为了HashSet能够正常工作,两个逻辑相等equals的对象hashcode必须相等,所以覆盖了equas方法必须同时覆盖hashcode方法。

TreeSet实现了排序。要排序就必须能够对两个对象进行比较,这就要求比较的对象必须实现Comparable接口(其中包含compareTo方法)。

 关于Equals方法和compareTo方法的实现:

(1)共同点:实现的功能差不多,都是对原有方法进行覆盖。但是Equals方法是来自于Object最原始的类,而compareTo是来自于Comparable接口。基本思想就是将对象内部的各部分进行比较,若都相同则判定相等。

(2)不同点:

public boolean equals(Object obj) ;

public int compareTo(PhoneNum o);

很多人覆盖equals用的参数是MyClass自己的类,必须得是Object类,否则不会进行覆盖override,而是重载overload!

Equals方法的通用过程:

1)用’==’判断是否同一对象的引用

2)使用instanceof或者getClass判断是否同一类型

3)将Object转化为正确类型

4)对该类中的关键域进行逐个比较,判断是否相等

package com.zgd;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

class PhoneNum implements Comparable<PhoneNum>{
	private int areaNum;
	private int numPart1;
	private int numPart2;
	
	public int getAreaNum() {
		return areaNum;
	}
	public void setAreaNum(int areaNum) {
		this.areaNum = areaNum;
	}
	public int getNumPart1() {
		return numPart1;
	}
	public void setNumPart1(int numPart1) {
		this.numPart1 = numPart1;
	}
	public int getNumPart2() {
		return numPart2;
	}
	public void setNumPart2(int numPart2) {
		this.numPart2 = numPart2;
	}
	
	@Override
	public String toString() {
		return "PhoneNum [areaNum=" + areaNum + ", numPart1=" + numPart1
				+ ", numPart2=" + numPart2 + "]";
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + areaNum;
		result = prime * result + numPart1;
		result = prime * result + numPart2;
		return result;
	}
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())//防止因为是子类而带来的问题
			return false;
		PhoneNum other = (PhoneNum) obj;
		if (areaNum != other.areaNum)//这里因为实在这个函数里面,所以可以直接引用?
			return false;
		if (numPart1 != other.numPart1)
			return false;
		if (numPart2 != other.numPart2)
			return false;
		return true;
	}
	public PhoneNum(int areaNum, int numPart1, int numPart2) {
		super();
		this.areaNum = areaNum;
		this.numPart1 = numPart1;
		this.numPart2 = numPart2;
	}

	@Override
	public int compareTo(PhoneNum o) {
		// TODO Auto-generated method stub
		if(areaNum - o.getAreaNum() != 0){
			return areaNum - o.getAreaNum() ;
		}
		
		if(numPart1 - o.numPart1 != 0){
			return numPart1 - o.numPart1 ;
		}
		
		if(numPart2 - o.numPart2 != 0){
			return numPart2 - o.numPart2;
		}
		return 0;
	}
	
	
	
	
}


public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		//Set
		Set<PhoneNum> set_pn = new HashSet<PhoneNum>();
		
		set_pn.add(new PhoneNum(101,13811,320857));
		set_pn.add(new PhoneNum(103,13813,320859));
		set_pn.add(new PhoneNum(102,13814,320858));
		
		PhoneNum pn = new PhoneNum(101,13811,320857);
		
		PhoneNum pn2 = new PhoneNum(105,13811,320857);
//		
//		for(PhoneNum pn : set_pn){
//			System.out.println(pn.toString());
//		}
		
		
		Map<PhoneNum,String> map = new HashMap<PhoneNum,String>();
		map.put(new PhoneNum(101,13811,320857), "zenggd");
		map.put(new PhoneNum(103,13813,320859), "guodong");
		map.put(new PhoneNum(102,13812,320858), "harry");
		
		
		for(Map.Entry<PhoneNum, String> tt: map.entrySet()){
			System.out.println(tt.getKey() + " " + tt.getValue());
		}
		
//		List<Map.Entry<PhoneNum, String>> list= new ArrayList<Map.Entry<PhoneNum, String>>();
//		list.addAll(map.entrySet());
//		
//		Map.Entry<PhoneNum, String> temp = Collections.max(list, new Comparator<Map.Entry<PhoneNum, String>>() {
//
//			@Override
//			public int compare(Entry<PhoneNum, String> o1,
//					Entry<PhoneNum, String> o2) {
//				// TODO Auto-generated method stub
//				return o1.getKey().getAreaNum() - o2.getKey().getAreaNum();
//				//return 0;
//			}
//			
//		});
//		
//		System.out.println(temp.getKey());
		
//		for(PhoneNum pn_temp : map.keySet()){
//			//System.out.println(pn_temp+" "+map.get(pn_temp));
//		}
//		//List
		
		
//		PhoneNum tt = Collections.max(set_pn,new Comparator<PhoneNum>() {
//
//			@Override
//			public int compare(PhoneNum o1, PhoneNum o2) {
//				// TODO Auto-generated method stub
//				if(o1.getNumPart1() - o2.getNumPart2() != 0){
//					return o1.getNumPart1() - o2.getNumPart2();
//				}
//				
//				if(o1.getAreaNum() - o2.getAreaNum() != 0){
//					return o1.getAreaNum() - o2.getAreaNum() ;
//				}
//				return 0;
//			}
//		});

//
//		System.out.println(Float.floatToIntBits(3.444f));
//		System.out.println(Float.floatToIntBits(3.443f));
//		System.out.println(Float.compare(0.2f, 2.3f));
		//Map
	}

}

下面是eclipse自动生成的equals方法:

@Override
public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		PhoneNum other = (PhoneNum) obj;
		if (areaNum != other.areaNum)//other可以直接引用private属性return false;
			if (numPart1 != other.numPart1)
				return false;
		if (numPart2 != other.numPart2)
			return false;
		return true;
}
其中 Map.Entry<U,V>   相当于Map中的一个映射
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TreesetHashset的区别主要有以下几点: 1. 实现方式不同:Treeset是通过实现Comparable接口的compareTo方法来保证元素的唯一性和排序的,而Hashset是通过复写hashCode()方法和equals()方法来保证元素的唯一性的。 2. 底层数据结构不同:Treeset的底层数据结构是二叉树,可以对集合中的元素进行排序,这种结构可以提高排序性能。而Hashset的底层数据结构是哈希表,通过哈希值来存储元素,可以快速定位元素。 3. 元素的顺序不同:Treeset中的元素是按照元素的自然顺序进行排序的,或者根据自定义的比较器进行排序。而Hashset中的元素是无序的。 4. 判断元素唯一性的方式不同:Treeset是通过比较方法的返回值来判断元素是否重复,如果返回值为0,则代表元素重复。而Hashset是先判断元素的hashCode值是否相同,如果不同,则直接存储元素;如果相同,则再判断equals方法的返回值是否为true,如果为true,则视为同一个元素,不再存储。 综上所述,TreesetHashset在实现方式、底层数据结构、元素顺序和判断元素唯一性的方式上存在差异。 #### 引用[.reference_title] - *1* *3* [HashSetTreeSet的区别](https://blog.csdn.net/qq_42216184/article/details/84026603)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [HashsetTreeset的区别](https://blog.csdn.net/m0_37235955/article/details/105624398)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值