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中的一个映射