考慮實現Comparable介面
阿新 • • 發佈:2019-01-31
我們重寫實現
compareTo 實現自己的需求。
為什麼重寫?
原來的compareTo是空方法體, 很多類已實現該介面,目的就是為了排序,通過什麼排序,這就根據自己的業務邏輯了。
比如: public final class PhoneNumber implements Cloneable, Comparable<PhoneNumber> {... public static void main(String[] args) {...... TreeSet自身就實現了Comparable 介面 s.add就會呼叫TreeSert.java 內部方法NavigableSet<PhoneNumber> s = new TreeSet<PhoneNumber>(); for (int i = 0; i < 10; i++) s.add(randomPhoneNumber()); System.out.println(s);
return m.put(e, PRESENT)==null;
m.put就會呼叫TreeMap.java 內部put方法
/** * Associates the specified value with the specified key in this map. * If the map previously contained a mapping for the key, the old * value is replaced. * * @param key key with which the specified value is to be associated * @param value value to be associated with the specified key * * @return the previous value associated with <tt>key</tt>, or * <tt>null</tt> if there was no mapping for <tt>key</tt>. * (A <tt>null</tt> return can also indicate that the map * previously associated <tt>null</tt> with <tt>key</tt>.) * @throws ClassCastException if the specified key cannot be compared * with the keys currently in the map * @throws NullPointerException if the specified key is null * and this map uses natural ordering, or its comparator * does not permit null keys */ public V put(K key, V value) { Entry<K,V> t = root; if (t == null) { // TBD: // 5045147: (coll) Adding null to an empty TreeSet should // throw NullPointerException // // compare(key, key); // type check root = new Entry<K,V>(key, value, null); size = 1; modCount++; return null; } int cmp; Entry<K,V> parent; // split comparator and comparable paths Comparator<? super K> cpr = comparator; if (cpr != null) { do { parent = t; cmp = cpr.compare(key, t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); } else { if (key == null) throw new NullPointerException(); Comparable<? super K> k = (Comparable<? super K>) key; do { parent = t; cmp = k.compareTo(t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); } Entry<K,V> e = new Entry<K,V>(key, value, parent); if (cmp < 0) parent.left = e; else parent.right = e; fixAfterInsertion(e); size++; modCount++; return null; }
因為
cmp = k.compareTo(t.key);
我想重寫compareTo方法,實現自己的邏輯,所以我實現Comparable<PhoneNumber>介面,重寫它的方法。
----------------------------------------------------------------------------------------------------------------------------------------------------->api--------------------------------------
這個介面是什麼?
java.lang
介面 Comparable<T>
型別引數:
T - 可以與此物件進行比較的那些物件的型別
所有已知子介面:
Delayed, Name, RunnableScheduledFuture<V>, ScheduledFuture<V>
所有已知實現類:
Authenticator.RequestorType, BigDecimal, BigInteger, Boolean, Byte, ByteBuffer, Calendar, Character, CharBuffer, Charset, ClientInfoStatus, CollationKey, Component.BaselineResizeBehavior, CompositeName, CompoundName, Date, Date, Desktop.Action, Diagnostic.Kind, Dialog.ModalExclusionType, Dialog.ModalityType, Double, DoubleBuffer, DropMode, ElementKind, ElementType, Enum, File, Float, FloatBuffer, Formatter.BigDecimalLayoutForm, FormSubmitEvent.MethodType, GregorianCalendar, GroupLayout.Alignment, IntBuffer, Integer, JavaFileObject.Kind, JTable.PrintMode, KeyRep.Type, LayoutStyle.ComponentPlacement, LdapName, Long, LongBuffer, MappedByteBuffer, MemoryType, MessageContext.Scope, Modifier, MultipleGradientPaint.ColorSpaceType, MultipleGradientPaint.CycleMethod, NestingKind, Normalizer.Form, ObjectName, ObjectStreamField, Proxy.Type, Rdn, Resource.AuthenticationType, RetentionPolicy, RoundingMode, RowFilter.ComparisonType, RowIdLifetime, RowSorterEvent.Type, Service.Mode, Short, ShortBuffer, SOAPBinding.ParameterStyle, SOAPBinding.Style, SOAPBinding.Use, SortOrder, SourceVersion, SSLEngineResult.HandshakeStatus, SSLEngineResult.Status, StandardLocation, String, SwingWorker.StateValue, Thread.State, Time, Timestamp, TimeUnit, TrayIcon.MessageType, TypeKind, URI, UUID, WebParam.Mode, XmlAccessOrder, XmlAccessType, XmlNsForm
public interface Comparable<T>
此介面強行對實現它的每個類的物件進行整體排序。這種排序被稱為類的自然排序,類的 compareTo 方法被稱為它的自然比較方法。
實現此介面的物件列表(和陣列)可以通過 Collections.sort(和 Arrays.sort)進行自動排序。實現此介面的物件可以用作有序對映中的鍵或有序集合中的元素,無需指定比較器。
對於類 C 的每一個 e1 和 e2 來說,當且僅當 e1.compareTo(e2) == 0 與 e1.equals(e2) 具有相同的 boolean 值時,類 C 的自然排序才叫做與 equals 一致。注意,null 不是任何類的例項,即使 e.equals(null) 返回 false,e.compareTo(null) 也將丟擲 NullPointerException。
建議(雖然不是必需的)最好使自然排序與 equals 一致。這是因為在使用自然排序與 equals 不一致的元素(或鍵)時,沒有顯式比較器的有序集合(和有序對映表)行為表現“怪異”。尤其是,這樣的有序集合(或有序對映表)違背了根據 equals 方法定義的集合(或對映表)的常規協定。
例如,如果將兩個鍵 a 和 b 新增到沒有使用顯式比較器的有序集合中,使 (!a.equals(b) && a.compareTo(b) == 0),那麼第二個 add 操作將返回 false(有序集合的大小沒有增加),因為從有序集合的角度來看,a 和 b 是相等的。
實際上,所有實現 Comparable 的 Java 核心類都具有與 equals 一致的自然排序。java.math.BigDecimal 是個例外,它的自然排序將值相等但精確度不同的 BigDecimal 物件(比如 4.0 和 4.00)視為相等。
從數學上講,定義給定類 C 上自然排序的關係式 如下:
{(x, y)|x.compareTo(y) <= 0}。
整體排序的商 是:
{(x, y)|x.compareTo(y) == 0}。
它直接遵循 compareTo 的協定,商是 C 的等價關係,自然排序是 C 的整體排序。當說到類的自然排序與 equals 一致 時,是指自然排序的商是由類的 equals(Object) 方法定義的等價關係。
{(x, y)|x.equals(y)}。此介面是 Java Collections Framework 的成員。
方法詳細資訊 |
---|
compareTo
int compareTo(T o)比較此物件與指定物件的順序。如果該物件小於、等於或大於指定物件,則分別返回負整數、零或正整數。
實現類必須確保對於所有的 x 和 y 都存在 sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) 的關係。(這意味著如果 y.compareTo(x) 丟擲一個異常,則 x.compareTo(y) 也要丟擲一個異常。)
實現類還必須確保關係是可傳遞的:(x.compareTo(y)>0 && y.compareTo(z)>0) 意味著 x.compareTo(z)>0。
最後,實現者必須確保 x.compareTo(y)==0 意味著對於所有的 z,都存在 sgn(x.compareTo(z)) == sgn(y.compareTo(z))。 強烈推薦 (x.compareTo(y)==0) == (x.equals(y)) 這種做法,但並不是 嚴格要求這樣做。一般來說,任何實現 Comparable 介面和違背此條件的類都應該清楚地指出這一事實。推薦如此闡述:“注意:此類具有與 equals 不一致的自然排序。”
在前面的描述中,符號 sgn(expression) 指定 signum 數學函式,該函式根據 expression 的值是負數、零還是正數,分別返回 -1、0 或 1 中的一個值。
引數:
o - 要比較的物件。
返回:
負整數、零或正整數,根據此物件是小於、等於還是大於指定物件。
丟擲:
ClassCastException - 如果指定物件的型別不允許它與此物件進行比較。