Nauczyłem się używać porównywalnego, ale mam trudności z Komparatorem. Mam błąd w moim kodzie:
Exception in thread "main" java.lang.ClassCastException: New.People cannot be cast to java.lang.Comparable
at java.util.Arrays.mergeSort(Unknown Source)
at java.util.Arrays.sort(Unknown Source)
at java.util.Collections.sort(Unknown Source)
at New.TestPeople.main(TestPeople.java:18)
Oto mój kod:
import java.util.Comparator;
public class People implements Comparator {
private int id;
private String info;
private double price;
public People(int newid, String newinfo, double newprice) {
setid(newid);
setinfo(newinfo);
setprice(newprice);
}
public int getid() {
return id;
}
public void setid(int id) {
this.id = id;
}
public String getinfo() {
return info;
}
public void setinfo(String info) {
this.info = info;
}
public double getprice() {
return price;
}
public void setprice(double price) {
this.price = price;
}
public int compare(Object obj1, Object obj2) {
Integer p1 = ((People) obj1).getid();
Integer p2 = ((People) obj2).getid();
if (p1 > p2) {
return 1;
} else if (p1 < p2){
return -1;
} else {
return 0;
}
}
}
import java.util.ArrayList;
import java.util.Collections;
public class TestPeople {
public static void main(String[] args) {
ArrayList peps = new ArrayList();
peps.add(new People(123, "M", 14.25));
peps.add(new People(234, "M", 6.21));
peps.add(new People(362, "F", 9.23));
peps.add(new People(111, "M", 65.99));
peps.add(new People(535, "F", 9.23));
Collections.sort(peps);
for (int i = 0; i < peps.size(); i++){
System.out.println(peps.get(i));
}
}
}
Myślę, że ma to coś wspólnego z castingiem w metodzie porównawczej, ale bawiłem się tym i nadal nie mogłem znaleźć rozwiązania
java
sorting
comparator
Dan
źródło
źródło
Comparator<People>
,Comparable<People>
,List<People>
, itd.sort
. Jeśli masz użyćComparator<People>
, użyj 2-argumentusort
, a nie 1-argumentówsort
(co wymagaPeople implements Comparable<People>
).Odpowiedzi:
Jest kilka niezręcznych rzeczy z twoją przykładową klasą:
price
iinfo
(bardziej coś dla przedmiotów, a nie ludzi);W każdym razie, oto demonstracja, jak używać
Comparator<T>
:EDYTOWAĆ
Równoważne demo Java 8 wyglądałoby tak:
źródło
a.age - b.age
int
stackoverflow.com/questions/2728793/ ...Comparable
musisz wybrać pojedynczy atrybut do porównania. W przypadku osoby istnieje wiele atrybutów, które można porównać: wiek, długość, płeć, imiona itp. W takim przypadku łatwo jest podać kilka komparatorów, które wykonują te porównania.Oto bardzo krótki szablon do natychmiastowego sortowania:
jeśli trudno go zapamiętać, spróbuj po prostu zapamiętać, że jest podobny (pod względem znaku liczby) do:
To na wypadek, gdybyś chciał sortować w kolejności rosnącej: od najmniejszej do największej liczby.
źródło
compare()
historii.Użyj
People implements Comparable<People>
zamiast; to definiuje naturalny porządekPeople
.Comparator<People>
Może być również określona w dodatku, alePeople implements Comparator<People>
nie jest to właściwy sposób działania.Te dwa przeciążenia
Collections.sort
są różne:<T extends Comparable<? super T>> void sort(List<T> list)
Comparable
obiekty według ich naturalnego porządku<T> void sort(List<T> list, Comparator<? super T> c)
Comparator
Mylisz te dwie
Comparator
rzeczy, próbując posortować (i dlatego nie ma to sensuPerson implements Comparator<Person>
). Aby użyćCollections.sort
, potrzebujesz jednego z nich, aby był prawdziwy:Comparable
(użyj 1-argsort
)Comparator
Należy podać A dla typu (użyj 2-argssort
)Powiązane pytania
Ponadto, nie należy używać surowych typów w nowym kodem . Surowe typy są niebezpieczne i są dostarczane tylko w celu zapewnienia zgodności.
To znaczy zamiast tego:
powinieneś użyć ogólnej deklaracji bezpiecznej dla typów w następujący sposób:
Przekonasz się wtedy, że Twój kod nawet się nie kompiluje !! Byłoby to dobrze, ponieważ jest coś nie tak z kodem (
Person
nieimplements Comparable<Person>
), ale ponieważ użyłeś typu surowego, kompilator tego nie sprawdził i zamiast tego otrzymujeszClassCastException
w czasie wykonywania !!!Powinno to przekonać Cię do zawsze używania typów ogólnych bezpiecznych dla typów w nowym kodzie. Zawsze.
Zobacz też
źródło
W trosce o kompletność, oto prosta
compare
metoda jednowierszowa :źródło
signum
Integer.compare(lhs.getId(), rhs.getId());
to lepsze podejście. Jak wspomniano w @ niraj.nijju, odejmowanie może spowodować przepełnienie.Java 8 dodała nowy sposób tworzenia komparatorów, który zmniejsza ilość kodu, który musisz napisać, Comparator.comparing . Zobacz także Comparator.reversed
Oto próbka
źródło
Chcesz wdrożyć Porównywalny, a nie Komparator. Musisz zaimplementować metodę compareTo. Ale jesteś blisko. Komparator to procedura porównywania „innej firmy”. Porównywalne jest to, że przedmiot ten można porównać z innym.
Zauważ, że możesz chcieć sprawdzić tutaj wartości null dla getId ... na wszelki wypadek.
źródło
Oto przykład komparatora, który będzie działał dla dowolnej metody o zerowym argumencie, która zwraca wartość Porównywalną. Czy coś takiego istnieje w jdk lub bibliotece?
źródło
Ze względu na kompletność.
Korzystanie z Java8
jeśli chcesz
descending order
źródło
People::getId
?.thenComparing()
klauzulę, gdy wystąpi konflikt..thenComparing()
?źródło
Rozwiązanie można zoptymalizować w następujący sposób: Po pierwsze, użyj prywatnej klasy wewnętrznej, ponieważ zakres pól ma być klasą zamykającą TestPeople, aby implementacja klasy People nie była narażona na świat zewnętrzny. Można to zrozumieć w kategoriach tworzenia API, które oczekuje posortowanej listy osób Po drugie, używając wyrażenia Lamba (java 8), które redukuje kod, stąd wysiłek programistyczny
Stąd kod wyglądałby jak poniżej:
źródło
Powinieneś użyć przeciążonej metody sort (peps, new People ())
źródło
Oto moja odpowiedź na proste narzędzie porównawcze
}
Narzędzie do tego samego
}
Klasa informacji kolumny
źródło
Dwie poprawki:
Musisz zrobić
ArrayList
zPeople
obiektów:Po dodaniu obiektów do przygotowań użyj:
Dodaj również
CompareId
klasę jako:źródło
Nie trać czasu na samodzielne wdrażanie algorytmu sortowania. Zamiast; posługiwać się
Collections.sort () do sortowania danych.
źródło