正確重寫equals方法和compareTo方法



一、概述


程序要對一堆數據元素排序,查找,增加刪除。
數據節點

class Node{
        int type;
        int index;
        int score;
}

  

規則:
  1)對象相等:兩個節點n1與n2,如果n1.type == n2.type && n1.index == n2.index則n1等於n2
  2)排序:升序,比較score,score相同則比較type,type相同則比較index.
最開始我使用TreeMap存儲。實現Comparable接口,重寫equals方法與hashCode方法。
如下:

class Node implements Comparable<Node>{
	public int type;
	public int index;
	public int score;
	public Node(int t, int u, int s) {
		this.type = t;
		this.index = u;
		this.score = s;
	}
	@Override
	public int compareTo(Node o) {
		if(this.score != o.score) return this.score > o.score ? -1 : 1;
		else if(this.type != o.type) return this.type - o.type;
		else return this.index - o.index;
	}
	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		if(this == obj) return true;
		if(obj instanceof Node) {
			Node tn = (Node) obj;
			if(tn.type == this.type && tn.index == this.index) return true;
		}
		return false;
	}
	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return this.type + this.index;
	}
}

程序一直不對,經過兩個小時反復的檢查。我意識到,TreeMap比較對象是否相同也是調用CompareTo方法。equals和hashCode是HashMap那一套。
修改后,每個type的數據用一個TreeMap保存。
如下:

class Node implements Comparable<Node>{
	public int type;
	public int index;
	public int score;
	public Node(int t, int u, int s) {
		this.type = t;
		this.index = u;
		this.score = s;
	}
	@Override
	public int compareTo(Node o) {
		if(this.type == o.type && this.index == o.index) return 0;
		else {
			if(this.score != o.score) return this.score > o.score ? -1 : 1;
			else return this.index - o.index;
		}
	}
}

最后的排序使用優先隊列。
比較器:

Comparetor<Node> cmp = (x, y) ->{
	if(x.score != y.score) return x.score > y.score ? -1: 1;
	else if(x.type != y.type) return x.type - y.type;
	return x.index - y.index;
}

正確使用equals和compareTo,減少bug。


二、重寫equals


HashSet中存儲自己定義的對象,HashMap使用自定義的對象作Key,都需要重寫equals。同時要重寫hashCode.
hashCode定位,equals比較對象是否相同。
如下:

@Override
public boolean equals(Object obj) {//參數類型必須為Object,否則無效
	// TODO Auto-generated method stub
	if(this == obj) return true; //同引用
	if(obj instanceof Node) {//obj為null時,條件為假。
		Node tn = (Node) obj;
		if(tn.type == this.type && tn.index == this.index) return true;//根據內容比較對象
	}
	return false;
}

hashCode方法要保證相同對象的返回值相同。想實現一個好的hashCode比較難。


三、重寫compareTo


有序的集合,存儲自定以的對象都需要重寫compareTo方法或者提供該對象的比較器。常用到的集合有TreeMap(紅黑樹)、TreeSet、PriorityQueue(堆)、Arrays::sort(數組排序)、Collections::sort(List排序)。
如下:

class Data implements Comparable<Data>{ //實現Comparable接口
	@Override
	public int compareTo(Data o) {//小於返回負值,等於返回0,大於返回正值
		// TODO Auto-generated method stub
		return 0;
	}
}

比較器,如下:

Comparator<Node> cmp = new Comparator<Node>() {
		@Override
		public int compare(Node o1, Node o2) {
			// TODO Auto-generated method stub
			return 0;
		}
	};


使用Lambda表達式。

Comparetor<Node> cmp = (x, y) ->{
	if(x.score != y.score) return x.score > y.score ? -1: 1;
	else if(x.type != y.type) return x.type - y.type;
	return x.index - y.index;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM