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

本文探讨了HashSet与TreeSet在处理BigDecimal对象时的区别,并深入分析了equals方法与compareTo方法的实现细节及其对于集合操作的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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中的一个映射
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值