Bagaimana menyederhanakan implementasi compareTo () yang aman-nol?

157

Saya menerapkan compareTo()metode untuk kelas sederhana seperti ini (untuk dapat menggunakan Collections.sort()dan barang lain yang ditawarkan oleh platform Java):

public class Metadata implements Comparable<Metadata> {
    private String name;
    private String value;

// Imagine basic constructor and accessors here
// Irrelevant parts omitted
}

Saya ingin urutan alami untuk objek-objek ini adalah: 1) diurutkan berdasarkan nama dan 2) diurutkan berdasarkan nilai jika nama sama; kedua perbandingan harus peka terhadap huruf besar-kecil. Untuk kedua bidang, nilai nol sangat dapat diterima, jadi compareTojangan sampai putus dalam kasus ini.

Solusi yang muncul dalam pikiran adalah di sepanjang garis berikut (saya menggunakan "klausa penjaga" di sini sementara yang lain mungkin lebih suka satu titik kembali, tapi itu intinya):

// primarily by name, secondarily by value; null-safe; case-insensitive
public int compareTo(Metadata other) {
    if (this.name == null && other.name != null){
        return -1;
    }
    else if (this.name != null && other.name == null){
        return 1;
    }
    else if (this.name != null && other.name != null) {
        int result = this.name.compareToIgnoreCase(other.name);
        if (result != 0){
            return result;
        }
    }

    if (this.value == null) {
        return other.value == null ? 0 : -1;
    }
    if (other.value == null){
        return 1;
    }

    return this.value.compareToIgnoreCase(other.value);
}

Ini berhasil, tapi saya tidak sepenuhnya senang dengan kode ini. Memang itu tidak terlalu rumit, tetapi cukup bertele-tele dan membosankan.

Pertanyaannya adalah, bagaimana Anda membuat ini kurang bertele-tele (sambil mempertahankan fungsi)? Silakan merujuk ke perpustakaan standar Java atau Apache Commons jika mereka membantu. Apakah satu-satunya pilihan untuk membuat ini (sedikit) lebih sederhana adalah dengan mengimplementasikan "NullSafeStringComparator" saya sendiri, dan menerapkannya untuk membandingkan kedua bidang?

Suntingan 1-3 : Eddie benar; memperbaiki kasus "kedua nama adalah nol" di atas

Tentang jawaban yang diterima

Saya menanyakan pertanyaan ini pada tahun 2009, di Java 1.6 tentu saja, dan pada saat itu solusi JDK murni oleh Eddie adalah jawaban yang saya pilih. Saya tidak pernah sempat mengubah itu sampai sekarang (2017).

Ada juga solusi perpustakaan pihak ke-3 - Koleksi Apache Commons 2009 satu dan satu Guava 2013, keduanya diposting oleh saya - yang saya lebih suka di beberapa titik waktu.

Saya sekarang membuat solusi Java 8 bersih oleh Lukasz Wiktor jawaban yang diterima. Itu pasti harus disukai jika di Jawa 8, dan hari ini Java 8 harus tersedia untuk hampir semua proyek.

Jonik
sumber
stackoverflow.com/questions/369383/…
Ciro Santilli 郝海东 冠状 病 六四 事件 事件 法轮功

Jawaban:

173

Menggunakan Java 8 :

private static Comparator<String> nullSafeStringComparator = Comparator
        .nullsFirst(String::compareToIgnoreCase); 

private static Comparator<Metadata> metadataComparator = Comparator
        .comparing(Metadata::getName, nullSafeStringComparator)
        .thenComparing(Metadata::getValue, nullSafeStringComparator);

public int compareTo(Metadata that) {
    return metadataComparator.compare(this, that);
}
Lukasz Wiktor
sumber
7
Saya mendukung penggunaan Java 8 built-in stuff yang mendukung Apache Commons Lang, tetapi kode Java 8 itu cukup jelek, dan masih verbose. Saya akan tetap dengan org.apache.commons.lang3.builder.CompareToBuilder untuk saat ini.
jschreiner
1
Ini tidak berfungsi untuk Collections.sort (Arrays.asList (null, val1, null, val2, null)) karena ia akan mencoba memanggil compareTo () pada objek null. Sepertinya masalah dengan kerangka koleksi jujur, mencoba mencari cara untuk menyudutkan ini.
Pedro Borges
3
@PedroBorges Penulis bertanya tentang menyortir objek kontainer yang memiliki bidang yang dapat diurutkan (di mana bidang tersebut mungkin nol), bukan tentang menyortir referensi wadah nol. Jadi, sementara komentar Anda benar, di mana Collections.sort(List)itu tidak berfungsi ketika Daftar berisi nol, komentar itu tidak relevan dengan pertanyaan.
Scrubbie
211

Anda cukup menggunakan Apache Commons Lang :

result = ObjectUtils.compare(firstComparable, secondComparable)
Dag
sumber
4
(@Kong: Ini menangani null-safety tetapi bukan case-insensitivity yang merupakan aspek lain dari pertanyaan awal. Dengan demikian tidak mengubah jawaban yang diterima.)
Jonik
3
Juga, dalam pikiran saya Apache Commons seharusnya tidak menjadi jawaban yang diterima pada tahun 2013. (Bahkan jika beberapa sub proyek lebih baik dipertahankan daripada yang lain.) Jambu biji dapat digunakan untuk mencapai hal yang sama ; lihat nullsFirst()/ nullsLast().
Jonik
8
@Jonik Mengapa menurut Anda Apache Commons tidak boleh menjadi jawaban yang diterima pada tahun 2013?
reallynice
1
Bagian besar dari Apache Commons adalah barang warisan / tidak terpelihara / berkualitas rendah. Ada alternatif yang lebih baik untuk sebagian besar hal yang disediakannya, misalnya dalam Jambu Biji yang merupakan lib berkualitas sangat tinggi di seluruh, dan semakin banyak di JDK itu sendiri. Sekitar tahun 2005 ya, Apache Commons adalah omong kosong, tetapi hari ini tidak perlu di sebagian besar proyek. (Tentu, ada pengecualian; misalnya jika saya memerlukan klien FTP untuk beberapa alasan, saya mungkin akan menggunakan yang di Apache Commons Net, dan sebagainya.)
Jonik
6
@Jonik, bagaimana Anda menjawab pertanyaan menggunakan Guava? Pernyataan Anda bahwa Apache Commons Lang (paket org.apache.commons.lang3) adalah "warisan / tidak terawat / berkualitas rendah" adalah palsu atau paling tidak tidak berdasar. Commons Lang3 mudah dimengerti dan digunakan, dan itu dipelihara secara aktif. Mungkin pustaka saya yang paling sering digunakan (terlepas dari Spring Framework dan Spring Security) - kelas StringUtils dengan metode null-safe membuat normalisasi input menjadi sepele, misalnya.
Paul
93

Saya akan menerapkan pembanding aman nol. Mungkin ada implementasi di luar sana, tetapi ini sangat mudah diterapkan sehingga saya selalu menjalankannya sendiri.

Catatan: Komparator Anda di atas, jika kedua nama adalah nol, bahkan tidak akan membandingkan bidang nilai. Saya tidak berpikir ini yang Anda inginkan.

Saya akan menerapkan ini dengan sesuatu seperti berikut:

// primarily by name, secondarily by value; null-safe; case-insensitive
public int compareTo(final Metadata other) {

    if (other == null) {
        throw new NullPointerException();
    }

    int result = nullSafeStringComparator(this.name, other.name);
    if (result != 0) {
        return result;
    }

    return nullSafeStringComparator(this.value, other.value);
}

public static int nullSafeStringComparator(final String one, final String two) {
    if (one == null ^ two == null) {
        return (one == null) ? -1 : 1;
    }

    if (one == null && two == null) {
        return 0;
    }

    return one.compareToIgnoreCase(two);
}

EDIT: Memperbaiki kesalahan ketik dalam sampel kode. Itulah yang saya dapatkan karena tidak mengujinya terlebih dahulu!

EDIT: Promosi nullSafeStringComparator ke statis.

Eddie
sumber
2
Mengenai bersarang "jika" ... Saya menemukan bersarang jika menjadi kurang mudah dibaca untuk kasus ini, jadi saya menghindarinya. Ya, kadang-kadang akan ada perbandingan yang tidak perlu karena ini. final untuk parameter tidak diperlukan, tetapi merupakan ide yang bagus.
Eddie
31
Penggunaan manis XOR
James McMahon
9
@ Phihag - Saya tahu ini sudah lebih dari 3 tahun, TETAPI ... finalkata kunci tidak benar-benar diperlukan (kode Java sudah verbose sebagaimana adanya.) Namun, itu mencegah penggunaan kembali parameter sebagai vars lokal (praktik pengkodean yang mengerikan.) As pemahaman kolektif kita tentang perangkat lunak menjadi lebih baik seiring waktu, kita tahu bahwa segala sesuatunya harus final / const / inmutable secara default. Jadi saya lebih suka sedikit verbositas tambahan dalam menggunakan finaldalam deklarasi parameter (namun sepele fungsi mungkin) untuk mendapatkan inmutability-by-quasi-default.) Kelengkapan biaya overhead / pemeliharaan itu diabaikan dalam skema hal-hal besar.
luis.espinal
24
@ James McMahon saya harus tidak setuju. Xor (^) bisa saja diganti dengan yang tidak sama (! =). Ia bahkan mengkompilasi ke kode byte yang sama. Penggunaan! = Vs ^ hanyalah masalah selera dan keterbacaan. Jadi, menilai dari fakta bahwa Anda terkejut saya akan mengatakan bahwa itu bukan milik sini. Gunakan xor ketika Anda mencoba untuk menghitung checksum. Dalam kebanyakan kasus lain (seperti ini) mari kita berpegang teguh pada! =.
bvdb
5
Mudah untuk memperluas jawaban ini dengan mengganti String dengan T, T yang dideklarasikan sebagai <T extends Comparable <T>> ... dan kemudian kita dapat dengan aman membandingkan objek yang dapat diperbandingkan yang dapat dibatalkan
Thierry
20

Lihat bagian bawah jawaban ini untuk solusi yang diperbarui (2013) menggunakan Guava.


Inilah yang akhirnya saya ikuti. Ternyata kami sudah memiliki metode utilitas untuk perbandingan String null-safe, jadi solusi paling sederhana adalah memanfaatkannya. (Ini basis kode besar; mudah untuk melewatkan hal semacam ini :)

public int compareTo(Metadata other) {
    int result = StringUtils.compare(this.getName(), other.getName(), true);
    if (result != 0) {
        return result;
    }
    return StringUtils.compare(this.getValue(), other.getValue(), true);
}

Ini adalah bagaimana helper didefinisikan (itu kelebihan beban sehingga Anda juga dapat menentukan apakah nulls datang pertama atau terakhir, jika Anda mau):

public static int compare(String s1, String s2, boolean ignoreCase) { ... }

Jadi ini pada dasarnya sama dengan jawaban Eddie (walaupun saya tidak akan menyebut metode pembantu statis sebagai pembanding ) dan juga dari uzhin .

Bagaimanapun, secara umum, saya akan sangat menyukai solusi Patrick , karena saya pikir itu praktik yang baik untuk menggunakan perpustakaan yang sudah ada kapan pun memungkinkan. ( Ketahui dan gunakan perpustakaan seperti yang dikatakan Josh Bloch.) Tetapi dalam hal ini tidak akan menghasilkan kode yang paling bersih dan paling sederhana.

Edit (2009): Versi Koleksi Apache Commons

Sebenarnya, inilah cara untuk membuat solusi berdasarkan Apache Commons NullComparatorlebih sederhana. Gabungkan dengan case-insensitive yangComparator disediakan di Stringkelas:

public static final Comparator<String> NULL_SAFE_COMPARATOR 
    = new NullComparator(String.CASE_INSENSITIVE_ORDER);

@Override
public int compareTo(Metadata other) {
    int result = NULL_SAFE_COMPARATOR.compare(this.name, other.name);
    if (result != 0) {
        return result;
    }
    return NULL_SAFE_COMPARATOR.compare(this.value, other.value);
}

Sekarang ini cukup elegan, saya pikir. (Tinggal satu masalah kecil: Commons NullComparatortidak mendukung obat generik, jadi ada tugas yang tidak dicentang.)

Pembaruan (2013): Versi jambu

Hampir 5 tahun kemudian, inilah cara saya menangani pertanyaan awal saya. Jika pengkodean di Jawa, saya (tentu saja) akan menggunakan Jambu biji . (Dan tentu saja bukan Apache Commons.)

Letakkan konstanta ini di suatu tempat, misalnya di kelas "StringUtils":

public static final Ordering<String> CASE_INSENSITIVE_NULL_SAFE_ORDER =
    Ordering.from(String.CASE_INSENSITIVE_ORDER).nullsLast(); // or nullsFirst()

Kemudian, di public class Metadata implements Comparable<Metadata>:

@Override
public int compareTo(Metadata other) {
    int result = CASE_INSENSITIVE_NULL_SAFE_ORDER.compare(this.name, other.name);
    if (result != 0) {
        return result;
    }
    return CASE_INSENSITIVE_NULL_SAFE_ORDER.compare(this.value, other.value);
}    

Tentu saja, ini hampir identik dengan versi Apache Commons (keduanya menggunakan JASE CASE_INSENSITIVE_ORDER JDK ), penggunaan nullsLast()menjadi satu-satunya hal khusus Guava. Versi ini lebih disukai hanya karena Guava lebih disukai, sebagai ketergantungan, ke Commons Collections. (Karena semua orang setuju .)

Jika Anda bertanya-tanya tentang Ordering, catatan bahwa alat Comparator. Ini cukup berguna terutama untuk kebutuhan penyortiran yang lebih kompleks, memungkinkan Anda misalnya untuk menggunakan beberapa Pemesanan menggunakan compound(). Baca Pemesanan Dijelaskan untuk lebih lanjut!

Jonik
sumber
2
String.CASE_INSENSITIVE_ORDER benar-benar membuat solusinya jauh lebih bersih. Pembaruan yang bagus.
Patrick
2
Jika Anda tetap menggunakan Apache Commons, ComparatorChainmaka Anda tidak perlu menggunakan compareTometode sendiri .
amoebe
13

Saya selalu merekomendasikan menggunakan Apache commons karena kemungkinan besar akan lebih baik daripada yang Anda dapat menulis sendiri. Plus Anda kemudian dapat melakukan pekerjaan 'nyata' daripada menciptakan kembali.

Kelas yang Anda minati adalah Null Comparator . Ini memungkinkan Anda untuk membuat nulls tinggi atau rendah. Anda juga memberikan komparator sendiri untuk digunakan saat kedua nilai tersebut bukan nol.

Dalam kasus Anda, Anda dapat memiliki variabel anggota statis yang melakukan perbandingan dan kemudian compareTometode Anda hanya referensi itu.

Sesuatu seperti

class Metadata implements Comparable<Metadata> {
private String name;
private String value;

static NullComparator nullAndCaseInsensitveComparator = new NullComparator(
        new Comparator<String>() {

            @Override
            public int compare(String o1, String o2) {
                // inputs can't be null
                return o1.compareToIgnoreCase(o2);
            }

        });

@Override
public int compareTo(Metadata other) {
    if (other == null) {
        return 1;
    }
    int res = nullAndCaseInsensitveComparator.compare(name, other.name);
    if (res != 0)
        return res;

    return nullAndCaseInsensitveComparator.compare(value, other.value);
}

}

Bahkan jika Anda memutuskan untuk roll sendiri, ingat kelas ini karena sangat berguna ketika memesan daftar yang berisi elemen nol.

Patrick
sumber
Terima kasih, saya agak berharap akan ada sesuatu seperti ini di Commons! Namun dalam kasus ini, saya tidak menggunakannya: stackoverflow.com/questions/481813/…
Jonik
Baru menyadari bahwa pendekatan Anda dapat disederhanakan dengan menggunakan String.CASE_INSENSITIVE_ORDER; lihat jawaban tindak lanjut saya yang diedit.
Jonik
Ini bagus tetapi cek "if (other == null) {" tidak boleh ada di sana. Javadoc for Comparable mengatakan bahwa compareTo harus melempar NullPointerException jika yang lain adalah null.
Daniel Alexiuc
7

Saya tahu bahwa itu mungkin tidak langsung menjawab pertanyaan Anda, karena Anda mengatakan bahwa nilai nol harus didukung.

Tapi saya hanya ingin mencatat bahwa mendukung nulls di compareTo tidak sejalan dengan kontrak compareTo yang dijelaskan dalam javadocs resmi untuk Comparable :

Perhatikan bahwa null bukan turunan dari kelas mana pun, dan e.compareTo (null) harus melempar NullPointerException meskipun e.equals (null) mengembalikan false.

Jadi saya akan melempar NullPointerException secara eksplisit atau membiarkannya dilemparkan pertama kali ketika argumen nol sedang direferensikan.

Piotr Sobczyk
sumber
4

Anda dapat mengekstrak metode:

public int cmp(String txt, String otherTxt)
{
    if ( txt == null )
        return otjerTxt == null ? 0 : 1;

    if ( otherTxt == null )
          return 1;

    return txt.compareToIgnoreCase(otherTxt);
}

public int compareTo(Metadata other) {
   int result = cmp( name, other.name); 
   if ( result != 0 )  return result;
   return cmp( value, other.value); 

}

Yoni Roit
sumber
2
Haruskah "0: 1" tidak menjadi "0: -1"?
Rolf Kristensen
3

Anda dapat mendesain kelas Anda agar tidak berubah (Efektif Java 2nd Ed. Memiliki bagian yang hebat tentang hal ini, Butir 15: Minimalkan mutabilitas) dan pastikan pada konstruksi bahwa tidak ada null yang mungkin (dan gunakan pola objek nol jika diperlukan). Kemudian Anda dapat melewati semua cek itu dan dengan aman menganggap bahwa nilainya bukan nol.

Fabian Steeg
sumber
Ya, itu umumnya solusi yang baik, dan menyederhanakan banyak hal - tapi di sini aku lebih tertarik dalam kasus di mana nilai null diperbolehkan, untuk satu alasan atau lainnya, dan harus diperhitungkan :)
Jonik
2

Saya mencari sesuatu yang serupa dan ini tampak agak rumit jadi saya melakukan ini. Saya pikir ini sedikit lebih mudah dimengerti. Anda dapat menggunakannya sebagai pembanding atau sebagai satu liner. Untuk pertanyaan ini, Anda akan mengubah ke compareToIgnoreCase (). Seperti, nulls melayang. Anda dapat membalik 1, -1 jika Anda ingin mereka tenggelam.

StringUtil.NULL_SAFE_COMPARATOR.compare(getName(), o.getName());

.

public class StringUtil {
    public static final Comparator<String> NULL_SAFE_COMPARATOR = new Comparator<String>() {

        @Override
        public int compare(final String s1, final String s2) {
            if (s1 == s2) {
                //Nulls or exact equality
                return 0;
            } else if (s1 == null) {
                //s1 null and s2 not null, so s1 less
                return -1;
            } else if (s2 == null) {
                //s2 null and s1 not null, so s1 greater
                return 1;
            } else {
                return s1.compareTo(s2);
            }
        }
    }; 

    public static void main(String args[]) {
        final ArrayList<String> list = new ArrayList<String>(Arrays.asList(new String[]{"qad", "bad", "sad", null, "had"}));
        Collections.sort(list, NULL_SAFE_COMPARATOR);

        System.out.println(list);
    }
}
Dustin
sumber
2

kita bisa menggunakan java 8 untuk melakukan perbandingan ramah-null antara objek. seharusnya saya memiliki kelas Boy dengan 2 bidang: Nama string dan Integer age dan saya ingin pertama membandingkan nama dan kemudian usia jika keduanya sama.

static void test2() {
    List<Boy> list = new ArrayList<>();
    list.add(new Boy("Peter", null));
    list.add(new Boy("Tom", 24));
    list.add(new Boy("Peter", 20));
    list.add(new Boy("Peter", 23));
    list.add(new Boy("Peter", 18));
    list.add(new Boy(null, 19));
    list.add(new Boy(null, 12));
    list.add(new Boy(null, 24));
    list.add(new Boy("Peter", null));
    list.add(new Boy(null, 21));
    list.add(new Boy("John", 30));

    List<Boy> list2 = list.stream()
            .sorted(comparing(Boy::getName, 
                        nullsLast(naturalOrder()))
                   .thenComparing(Boy::getAge, 
                        nullsLast(naturalOrder())))
            .collect(toList());
    list2.stream().forEach(System.out::println);

}

private static class Boy {
    private String name;
    private Integer age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public Boy(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String toString() {
        return "name: " + name + " age: " + age;
    }
}

dan hasilnya:

    name: John age: 30
    name: Peter age: 18
    name: Peter age: 20
    name: Peter age: 23
    name: Peter age: null
    name: Peter age: null
    name: Tom age: 24
    name: null age: 12
    name: null age: 19
    name: null age: 21
    name: null age: 24
Leo Ng
sumber
1

Untuk kasus khusus di mana Anda tahu data tidak akan memiliki nol (selalu ide bagus untuk string) dan datanya sangat besar, Anda masih melakukan tiga perbandingan sebelum benar-benar membandingkan nilai, jika Anda yakin ini adalah kasus Anda , Anda dapat mengoptimalkan sedikit tad. YMMV sebagai kode yang dapat dibaca mengalahkan optimasi kecil:

        if(o1.name != null && o2.name != null){
            return o1.name.compareToIgnoreCase(o2.name);
        }
        // at least one is null
        return (o1.name == o2.name) ? 0 : (o1.name != null ? 1 : -1);
kisna
sumber
1
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Comparator;

public class TestClass {

    public static void main(String[] args) {

        Student s1 = new Student("1","Nikhil");
        Student s2 = new Student("1","*");
        Student s3 = new Student("1",null);
        Student s11 = new Student("2","Nikhil");
        Student s12 = new Student("2","*");
        Student s13 = new Student("2",null);
        List<Student> list = new ArrayList<Student>();
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s11);
        list.add(s12);
        list.add(s13);

        list.sort(Comparator.comparing(Student::getName,Comparator.nullsLast(Comparator.naturalOrder())));

        for (Iterator iterator = list.iterator(); iterator.hasNext();) {
            Student student = (Student) iterator.next();
            System.out.println(student);
        }


    }

}

output adalah

Student [name=*, id=1]
Student [name=*, id=2]
Student [name=Nikhil, id=1]
Student [name=Nikhil, id=2]
Student [name=null, id=1]
Student [name=null, id=2]
Nikhil Kumar K
sumber
1

Salah satu cara sederhana menggunakan NullSafe Comparator adalah dengan menggunakan implementasi Spring, di bawah ini adalah salah satu contoh sederhana untuk merujuk:

public int compare(Object o1, Object o2) {
        ValidationMessage m1 = (ValidationMessage) o1;
        ValidationMessage m2 = (ValidationMessage) o2;
        int c;
        if (m1.getTimestamp() == m2.getTimestamp()) {
            c = NullSafeComparator.NULLS_HIGH.compare(m1.getProperty(), m2.getProperty());
            if (c == 0) {
                c = m1.getSeverity().compareTo(m2.getSeverity());
                if (c == 0) {
                    c = m1.getMessage().compareTo(m2.getMessage());
                }
            }
        }
        else {
            c = (m1.getTimestamp() > m2.getTimestamp()) ? -1 : 1;
        }
        return c;
    }
Amandeep Singh
sumber
0

Contoh Apache ObjectUtils lain. Mampu mengurutkan jenis objek lainnya.

@Override
public int compare(Object o1, Object o2) {
    String s1 = ObjectUtils.toString(o1);
    String s2 = ObjectUtils.toString(o2);
    return s1.toLowerCase().compareTo(s2.toLowerCase());
}
snp0k
sumber
0

Ini adalah implementasi saya yang saya gunakan untuk mengurutkan ArrayList saya. kelas nol diurutkan ke yang terakhir.

untuk kasus saya, EntityPhone memperluas EntityAbstract dan wadah saya adalah Daftar <EntityAbstract>.

metode "compareIfNull ()" digunakan untuk pengurutan aman null. Metode lain adalah untuk kelengkapan, menunjukkan bagaimana comparIfNull dapat digunakan.

@Nullable
private static Integer compareIfNull(EntityPhone ep1, EntityPhone ep2) {

    if (ep1 == null || ep2 == null) {
        if (ep1 == ep2) {
            return 0;
        }
        return ep1 == null ? -1 : 1;
    }
    return null;
}

private static final Comparator<EntityAbstract> AbsComparatorByName = = new Comparator<EntityAbstract>() {
    @Override
    public int compare(EntityAbstract ea1, EntityAbstract ea2) {

    //sort type Phone first.
    EntityPhone ep1 = getEntityPhone(ea1);
    EntityPhone ep2 = getEntityPhone(ea2);

    //null compare
    Integer x = compareIfNull(ep1, ep2);
    if (x != null) return x;

    String name1 = ep1.getName().toUpperCase();
    String name2 = ep2.getName().toUpperCase();

    return name1.compareTo(name2);
}
}


private static EntityPhone getEntityPhone(EntityAbstract ea) { 
    return (ea != null && ea.getClass() == EntityPhone.class) ?
            (EntityPhone) ea : null;
}
Angel Koh
sumber
0

Jika Anda ingin Retas sederhana:

arrlist.sort((o1, o2) -> {
    if (o1.getName() == null) o1.setName("");
    if (o2.getName() == null) o2.setName("");

    return o1.getName().compareTo(o2.getName());
})

Jika Anda ingin meletakkan nulls di akhir daftar, ubah saja ini di metod di atas

return o2.getName().compareTo(o1.getName());
Orang Mars
sumber