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