国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java? 教程(對(duì)象排序)

Chao / 2061人閱讀

對(duì)象排序

List l可以如下排序。

Collections.sort(l);

如果List包含String元素,它將按字母順序排序,如果它由Date元素組成,它將按時(shí)間順序排序,這是怎么發(fā)生的?StringDate都實(shí)現(xiàn)了Comparable接口,Comparable實(shí)現(xiàn)為類提供了自然的順序,允許該類的對(duì)象自動(dòng)排序,下表總結(jié)了一些實(shí)現(xiàn)Comparable的更重要的Java平臺(tái)類。

自然排序
Byte 有符號(hào)數(shù)字
Character 無(wú)符號(hào)數(shù)字
Long 有符號(hào)數(shù)字
Integer 有符號(hào)數(shù)字
Short 有符號(hào)數(shù)字
Double 有符號(hào)數(shù)字
Float 有符號(hào)數(shù)字
BigInteger 有符號(hào)數(shù)字
BigDecimal 有符號(hào)數(shù)字
Boolean Boolean.FALSE < Boolean.TRUE
File 依賴于系統(tǒng)的路徑名稱上的字典
String 接字母順序
Date 按時(shí)間順序
CollationKey 特定于語(yǔ)言環(huán)境的字典

如果你嘗試對(duì)列表進(jìn)行排序,其中的元素未實(shí)現(xiàn)ComparableCollections.sort(list)將拋出ClassCastException,類似地,如果你嘗試使用comparator對(duì)其元素?zé)o法相互比較的列表進(jìn)行排序,則Collections.sort(list, comparator)將拋出ClassCastException。雖然不同類型的元素可以相互比較,但這里列出的類別都不允許進(jìn)行類間比較。

如果你只想對(duì)可比較元素的列表進(jìn)行排序或創(chuàng)建它們的已排序集合,那么你真正需要了解Comparable接口的所有內(nèi)容,如果要實(shí)現(xiàn)自己的Comparable類型,下一部分將是你感興趣的。

編寫(xiě)自己的Comparable類型

Comparable接口包含以下方法。

public interface Comparable {
    public int compareTo(T o);
}

compareTo方法將接收對(duì)象與指定對(duì)象進(jìn)行比較,并返回負(fù)整數(shù)、0或正整數(shù),具體取決于接收對(duì)象是否小于、等于或大于指定對(duì)象,如果無(wú)法將指定的對(duì)象與接收對(duì)象進(jìn)行比較,則該方法將拋出ClassCastException

以下表示人名的類實(shí)現(xiàn)了Comparable

import java.util.*;

public class Name implements Comparable {
    private final String firstName, lastName;

    public Name(String firstName, String lastName) {
        if (firstName == null || lastName == null)
            throw new NullPointerException();
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String firstName() { return firstName; }
    public String lastName()  { return lastName;  }

    public boolean equals(Object o) {
        if (!(o instanceof Name))
            return false;
        Name n = (Name) o;
        return n.firstName.equals(firstName) && n.lastName.equals(lastName);
    }

    public int hashCode() {
        return 31*firstName.hashCode() + lastName.hashCode();
    }

    public String toString() {
    return firstName + " " + lastName;
    }

    public int compareTo(Name n) {
        int lastCmp = lastName.compareTo(n.lastName);
        return (lastCmp != 0 ? lastCmp : firstName.compareTo(n.firstName));
    }
}

為了使前面的例子簡(jiǎn)短,該類有些限制:它不支持中間名,它要求名字和姓氏,并且它不以任何方式國(guó)際化,盡管如此,它還說(shuō)明了以下要點(diǎn):

Name對(duì)象是不可變的,在所有其他條件相同的情況下,不可變類型是解決問(wèn)題的方法,特別是對(duì)于將作為集合中的元素或Map中的鍵使用的對(duì)象,如果你在集合中修改元素或鍵,這些集合將會(huì)中斷。

構(gòu)造函數(shù)檢查其參數(shù)是否為null,這可以確保所有Name對(duì)象都格式正確,這樣其他任何方法都不會(huì)拋出NullPointerException

hashCode方法被重新定義,這對(duì)于重新定義equals方法的任何類都是必不可少的(等同對(duì)象必須具有相同的哈希碼)。

如果指定的對(duì)象為null或類型不合適,則equals方法返回falsecompareTo方法在這些情況下拋出運(yùn)行時(shí)異常,這兩種行為都是各自方法的一般契約所要求的。

toString方法已重新定義,因此它以人類可讀的形式打印Name,這總是一個(gè)好主意,特別是對(duì)于要放入集合的對(duì)象,各種集合類型的toString方法依賴于其元素、鍵和值的toString方法。

由于本節(jié)是關(guān)于元素排序的,讓我們?cè)僬務(wù)?b>Name的compareTo方法,它實(shí)現(xiàn)了標(biāo)準(zhǔn)的名稱排序算法,其中姓氏優(yōu)先于名字,這正是你想要的自然順序,如果自然順序不自然,那將會(huì)非常混亂!

看看compareTo是如何實(shí)現(xiàn)的,因?yàn)樗浅=?jīng)典,首先,比較對(duì)象的最重要部分(在本例中為姓氏),通常,你可以只使用部分類型的自然順序,在這種情況下,該部分是一個(gè)字符串,自然(詞典)排序正是所要求的。如果比較的結(jié)果不是0(代表相等),那么就完成了:你只需返回結(jié)果。如果最重要的部分相同,則繼續(xù)比較下一個(gè)最重要的部分,在這種情況下,只有兩個(gè)部分 — 名字和姓氏。如果有更多的部分,你會(huì)以明顯的方式進(jìn)行,比較部分,直到你發(fā)現(xiàn)兩個(gè)不相等或你正在比較最不重要的部分,此時(shí)你將返回比較的結(jié)果。

為了說(shuō)明這一切都是有效的,這里有一個(gè)程序,它構(gòu)建了一個(gè)名稱列表并對(duì)它們進(jìn)行排序。

import java.util.*;

public class NameSort {
    public static void main(String[] args) {
        Name[] nameArray = {
                new Name("John", "Smith"),
                new Name("Karl", "Ng"),
                new Name("Jeff", "Smith"),
                new Name("Tom", "Rich")
        };

        List names = Arrays.asList(nameArray);
        Collections.sort(names);
        System.out.println(names);
    }
}

如果你運(yùn)行這個(gè)程序,這是它打印的內(nèi)容。

[Karl Ng, Tom Rich, Jeff Smith, John Smith]

compareTo方法的行為有四個(gè)限制,我們現(xiàn)在不會(huì)討論它們,因?yàn)樗鼈兿喈?dāng)技術(shù)性和枯燥,最好留在API文檔中,實(shí)現(xiàn)Comparable的所有類都遵守這些限制非常重要,因此如果你正在編寫(xiě)實(shí)現(xiàn)它的類,請(qǐng)閱讀Comparable的文檔。嘗試對(duì)違反限制的對(duì)象列表進(jìn)行排序具有未定義的行為,從技術(shù)上講,這些限制確保自然順序是實(shí)現(xiàn)它的類的對(duì)象的總順序,這對(duì)于確保明確定義排序是必要的。

Comparators

如果你想按一些對(duì)象的自然順序以外的順序排序,該怎么辦?或者,如果要對(duì)某些未實(shí)現(xiàn)Comparable的對(duì)象進(jìn)行排序,該怎么辦?要執(zhí)行上述任一操作,你需要提供Comparator — 一個(gè)封裝排序的對(duì)象,與Comparable接口一樣,Comparator接口由單個(gè)方法組成。

public interface Comparator {
    int compare(T o1, T o2);
}

compare方法比較它的兩個(gè)參數(shù),返回一個(gè)負(fù)整數(shù)、0或一個(gè)正整數(shù),具體取決于第一個(gè)參數(shù)是小于、等于還是大于第二個(gè)參數(shù),如果其中一個(gè)參數(shù)的Comparator類型不合適,則compare方法將拋出ClassCastException

關(guān)于Comparable的大部分內(nèi)容也適用于Comparator,編寫(xiě)compare方法與編寫(xiě)compareTo方法幾乎完全相同,只是前者將兩個(gè)對(duì)象作為參數(shù)傳入,由于同樣的原因,compare方法必須遵守與ComparablecompareTo方法相同的四個(gè)技術(shù)限制 — Comparator必須對(duì)它所比較的??對(duì)象產(chǎn)生總順序。

假設(shè)你有一個(gè)名為Employee的類,如下所示。

public class Employee implements Comparable {
    public Name name()     { ... }
    public int number()    { ... }
    public Date hireDate() { ... }
       ...
}

讓我們假設(shè)Employee實(shí)例的自然順序是員工姓名上的Name排序(如上例所定義),不幸的是,老板要求按照資歷順序列出員工名單。這意味著我們必須做一些工作,但并不多,以下程序?qū)⑸伤璧牧斜怼?/p>

import java.util.*;
public class EmpSort {
    static final Comparator SENIORITY_ORDER = 
                                        new Comparator() {
            public int compare(Employee e1, Employee e2) {
                return e2.hireDate().compareTo(e1.hireDate());
            }
    };

    // Employee database
    static final Collection employees = ... ;

    public static void main(String[] args) {
        List e = new ArrayList(employees);
        Collections.sort(e, SENIORITY_ORDER);
        System.out.println(e);
    }
}

程序中的Comparator相當(dāng)簡(jiǎn)單,它依賴于應(yīng)用于hireDate訪問(wèn)器方法返回的值的Date的自然順序,注意,Comparator將第二個(gè)參數(shù)的雇用日期傳遞給第一個(gè)參數(shù),而不是反過(guò)來(lái),原因是最近招聘的員工級(jí)別最低,按雇用日期順序排序會(huì)使該名單的資歷順序相反,人們有時(shí)用來(lái)達(dá)到這種效果的另一種技術(shù)是保持參數(shù)順序,但要否定比較的結(jié)果。

// Don"t do this!!
return -r1.hireDate().compareTo(r2.hireDate());

你應(yīng)該總是使用前一種技術(shù)來(lái)支持后者,因?yàn)楹笳卟荒鼙WC有效,這樣做的原因是compareTo方法可以返回任何負(fù)整數(shù),如果它的參數(shù)小于調(diào)用它的對(duì)象。有一個(gè)負(fù)整型數(shù)在被否定時(shí)仍然是負(fù)的,盡管這看起來(lái)很奇怪。

-Integer.MIN_VALUE == Integer.MIN_VALUE

上一個(gè)程序中的Comparator可以很好地對(duì)List進(jìn)行排序,但確實(shí)存在一個(gè)缺陷:它不能用于排序已排序的集合,例如TreeSet,因?yàn)樗傻捻樞蚺cequals不兼容,這意味著這個(gè)Comparator相當(dāng)于equals方法所沒(méi)有的對(duì)象。特別是,在同一天雇傭的任何兩名員工將相等,當(dāng)你對(duì)List進(jìn)行排序時(shí),這并不重要,但是當(dāng)你使用Comparator來(lái)排序一個(gè)已排序的集合時(shí),它是致命的,如果你使用此Comparator將在同一日期雇用的多名員工插入到TreeSet中,則只會(huì)將第一個(gè)員工添加到該集合中,第二個(gè)將被視為重復(fù)元素,將被忽略。

要解決此問(wèn)題,只需調(diào)整Comparator,以便生成與equals兼容的排序,換句話說(shuō),調(diào)整它以便在使用compare時(shí)看到相同的唯一元素是那些在使用equals進(jìn)行比較時(shí)也被視為相等的元素。執(zhí)行此操作的方法是執(zhí)行兩部分比較(像對(duì)于Name),其中第一部分是我們感興趣的部分 — 在這種情況下,是雇用日期 — 第二部分是唯一標(biāo)識(shí)對(duì)象的屬性,員工編號(hào)在這里是明顯的屬性,這是比較器的結(jié)果。

static final Comparator SENIORITY_ORDER = 
                                        new Comparator() {
    public int compare(Employee e1, Employee e2) {
        int dateCmp = e2.hireDate().compareTo(e1.hireDate());
        if (dateCmp != 0)
            return dateCmp;

        return (e1.number() < e2.number() ? -1 :
               (e1.number() == e2.number() ? 0 : 1));
    }
};

最后一點(diǎn):你可能想要使用更簡(jiǎn)單的方法替換Comparator中的最終return語(yǔ)句:

return e1.number() - e2.number();

除非你絕對(duì)確定沒(méi)有人會(huì)有負(fù)的員工編號(hào),否則不要這樣做!這個(gè)技巧通常不起作用,因?yàn)閹Х?hào)整數(shù)類型不夠大,不能表示兩個(gè)任意帶符號(hào)整數(shù)的差,如果i是一個(gè)大的正整數(shù)且j是一個(gè)大的負(fù)整數(shù),i - j將溢出并返回一個(gè)負(fù)整數(shù),由此產(chǎn)生的comparator違反了我們一直在討論的四個(gè)技術(shù)限制之一(傳遞性)并產(chǎn)生可怕的、微妙的錯(cuò)誤,這不是純粹的理論問(wèn)題。

上一篇:Map接口 下一篇:SortedSet接口

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/73965.html

相關(guān)文章

  • Java? 教程(集合接口)

    集合接口 核心集合接口封裝了不同類型的集合,如下圖所示,這些接口允許獨(dú)立于其表示的細(xì)節(jié)來(lái)操縱集合,核心集合接口是Java集合框架的基礎(chǔ),如下圖所示,核心集合接口形成層次結(jié)構(gòu)。 showImg(https://segmentfault.com/img/bVbntJW?w=402&h=146); Set是一種特殊的Collection,SortedSet是一種特殊的Set,依此類推,另請(qǐng)注意,層次結(jié)構(gòu)...

    elisa.yang 評(píng)論0 收藏0
  • 程序兵法:Java String 源碼的排序算法(一)

    摘要:從行,可以看出字符串的存儲(chǔ)結(jié)構(gòu)是字符數(shù)組。如果不相等,則返回兩字符的編碼值的差值第行當(dāng)前字符串和另一個(gè)字符串,依次字符比較。如果均相等,則返回兩個(gè)字符串長(zhǎng)度的差值所以要排序,肯定先有比較能力,即實(shí)現(xiàn)接口。摘要: 原創(chuàng)出處 https://www.bysocket.com 「公眾號(hào):泥瓦匠BYSocket 」歡迎關(guān)注和轉(zhuǎn)載,保留摘要,謝謝!這是泥瓦匠的第103篇原創(chuàng)《程序兵法:Java Str...

    CntChen 評(píng)論0 收藏0
  • Java? 教程(Queue接口)

    Queue接口 Queue是在處理之前保存元素的集合,除了基本的Collection操作外,隊(duì)列還提供額外的插入、刪除和檢查操作,Queue接口如下。 public interface Queue extends Collection { E element(); boolean offer(E e); E peek(); E poll(); E remov...

    RayKr 評(píng)論0 收藏0
  • Java 8 簡(jiǎn)明教程

    摘要:簡(jiǎn)明教程原文譯者黃小非來(lái)源簡(jiǎn)明教程并沒(méi)有沒(méi)落,人們很快就會(huì)發(fā)現(xiàn)這一點(diǎn)歡迎閱讀我編寫(xiě)的介紹。編譯器會(huì)自動(dòng)地選擇合適的構(gòu)造函數(shù)來(lái)匹配函數(shù)的簽名,并選擇正確的構(gòu)造函數(shù)形式。 Java 8 簡(jiǎn)明教程 原文:Java 8 Tutorial 譯者:ImportNew.com - 黃小非 來(lái)源:Java 8簡(jiǎn)明教程 ? Java并沒(méi)有沒(méi)落,人們很快就會(huì)發(fā)現(xiàn)這一點(diǎn) 歡迎閱讀我編寫(xiě)的Java ...

    testHs 評(píng)論0 收藏0
  • Java? 教程(默認(rèn)方法)

    默認(rèn)方法 接口部分描述了一個(gè)涉及計(jì)算機(jī)控制汽車(chē)制造商的例子,他們發(fā)布了行業(yè)標(biāo)準(zhǔn)接口,描述了可以調(diào)用哪些方法來(lái)操作他們的汽車(chē),如果那些計(jì)算機(jī)控制的汽車(chē)制造商為他們的汽車(chē)添加新的功能,如飛行,該怎么辦?這些制造商需要指定新的方法,以使其他公司(如電子制導(dǎo)儀器制造商)能夠使其軟件適應(yīng)飛行汽車(chē),這些汽車(chē)制造商將在哪里聲明這些與飛行有關(guān)的新方法?如果他們將它們添加到原始接口,那么實(shí)現(xiàn)了這些接口的程序員將不得...

    zhisheng 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<