一、概述
程序要對一堆數據元素排序,查找,增加刪除。
數據節點
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;
}
