2010-11-22 15 views
31

Ho scritto il seguente codice:comparatore con il doppio tipo

public class NewClass2 implements Comparator<Point> 
{ 
    public int compare(Point p1, Point p2) 
    { 
     return (int)(p1.getY() - p2.getY()); 
    } 
} 

Se diciamo che hanno due numeri doppi, 3.2 - 3.1, la differenza dovrebbe essere 0.1. Quando lancio il numero su int, tuttavia, la differenza termina con 0, che non è corretto.

Ho quindi bisogno di compare() per restituire un doppio, non un int. Il problema è che il mio campo getX è un doppio. Come posso risolvere questo problema?

risposta

59

non è necessario tornare double.

L'interfaccia Comparator viene utilizzata per stabilire un ordine per gli elementi da confrontare. Avere campi che utilizzano double è irrilevante per questo ordine.

Il tuo codice è a posto.

dispiace, ho sbagliato, leggendo di nuovo la domanda, questo è quello che vi serve:

public class NewClass2 implements Comparator<Point> { 
    public int compare(Point p1, Point p2) { 
     if (p1.getY() < p2.getY()) return -1; 
     if (p1.getY() > p2.getY()) return 1; 
     return 0; 
    }  
} 
+4

Penso che questo non funzionerà con 'NaN' e' * _INFINITY' – Jerome

7

Il metodo compare deve restituire un int. È un numero che è o:

  • Meno di zero, se il primo valore è inferiore del secondo;
  • uguale a a zero, se i due valori sono uguale a;
  • maggiore di rispetto allo zero, se il primo valore è maggiore rispetto al secondo;

Non c'è bisogno per restituire un double. È restituire un int per implementare l'interfaccia Comparator. Devi solo restituire il corretto int, in base alle regole che ho descritto sopra.

Non si può semplicemente lanciare da int, come, come hai detto tu, una differenza di 0.1 si tradurrà in 0. Si può semplicemente fare questo:

public int compare(Point p1, Point p2) 
{ 
    double delta= p1.getY() - p2.getY(); 
    if(delta > 0) return 1; 
    if(delta < 0) return -1; 
    return 0; 
} 

Ma dal confronto dei valori a virgola mobile è sempre fastidioso, si dovrebbe confrontare all'interno di un certo range (vedi this question), qualcosa di simile:

public int compare(Point p1, Point p2) 
{ 
    double delta = p1.getY() - p2.getY(); 
    if(delta > 0.00001) return 1; 
    if(delta < -0.00001) return -1; 
    return 0; 
} 
+0

grazie per la risposta completa! Ottengo il tutto! Non mi dimentico mai di questo in questo modo – user472221

78

vi suggerisco di utilizzare il metodo integrato Double.compare(). Se hai bisogno che un intervallo per i valori doppi sia uguale puoi usare chcek per primo.

return Double.compare(p1.getY(), p2.gety()); 

o

if(Math.abs(p1.getY()-p2.getY()) < ERR) return 0;  
return Double.compare(p1.getY(), p2.gety()); 

Il problema con l'utilizzo e <> è che NaN restituisce false in entrambi i casi ad una gestione possibilmente incoerente. per esempio. NaN è definito come non uguale a nulla, anche se stesso nelle soluzioni di @ suihock e @ Martinho, se entrambi i valori sono NaN il metodo restituirà 0 ogni volta, il che implica che NaN è uguale a tutto.

+3

Java 7 aggiunto compare() per consistenza 'Long' e' Integer'. –

+1

Ecco un [collegamento al codice sorgente] (http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/Double.java#lnmr- 999) di 'Double.compare()' per vedere come gestisce 'NaN'. – xdhmoore

+0

Probabilmente si potrebbe anche usare 'Math.signum' se si desidera un comportamento leggermente diverso sui NaN. – xdhmoore

0

Bene, è possibile moltiplicare quei valori doppi di un fattore appropriato prima di convertirlo in numero intero, ad es. nel tuo caso dal suo unico decimale quindi 10 sarebbe un buon fattore;

return (int)(p1.getY()*10 - p2.getY()*10); 
+0

Questa risposta funziona solo in determinate circostanze. Cioè moltiplicando per 10 si otterrà il doppio valore diventando un numero intero. – robjwilkins

+0

@robjwilkins: Potrebbe chiarire che in tal caso questo metodo di scelta di un fattore appropriato non funzionerebbe? – HasnainMamdani

+0

Non funziona nel caso in cui getY restituisca un numero che non può essere moltiplicato per 10 per ottenere un numero intero. Ad esempio, se getY restituisce 3.2111, questa soluzione non funzionerà. Poiché getY restituisce un doppio, è del tutto fattibile restituire 3.2111. Questa soluzione è quindi molto limitata e ci sono alternative molto migliori. – robjwilkins

2

voglio solo ampliare Peter Lawrey risposta su JDK 8, se lo si fa in questo modo:

public class NewClass2 implements Comparator<Point> { 
    public int compare(Point p1, Point p2) { 
     return Double.compare(p1.getY(), p2.gety()); 
    }  
} 

Si potrebbe definire questo comparatore utilizzando un'espressione lambda abbastanza facilmente

(Point p1,Point p2) -> Double.compare(p1.getY(), p2.gety()) 

Meglio ancora, è possibile utilizzare un riferimento membro come questo:

Double::compare 
+1

Mi piace l'uso del lambda in questa risposta, è un ottimo suggerimento. Non capisco come si possa usare un riferimento ai membri? Potresti fornire un esempio? grazie – robjwilkins

6

Dal momento che Java 1.8 è possibile utilizzare anche

Comparator.comparingDouble(p -> p.getY()) 
1

Usa Double.compare(/**double value 1*/, /**double value 2*/); con un nuovo comparatore per la doppia valenza classe del modello.

public static List<MyModel> sortByDouble(List<MyModel> modelList) { 
     Collections.sort(modelList, new Comparator<MyModel>() { 
      @Override 
      public int compare(MyModels1, MyModels2) { 
       double s1Distance = Double.parseDouble(!TextUtils.isEmpty(s1.distance) ? s1.distance : "0"); 
       double s2Distance = Double.parseDouble(!TextUtils.isEmpty(s2.distance) ? s2.distance : "0"); 
       return Double.compare(s1Distance, s2Distance); 
      } 
     }); 
     return modelList; 
    } 
+0

Nota che puoi ripristinare l'ordinamento utilizzando Double.compare (d2, d1) invece di Double.compare (d1, d2). Ovvio ma fermo. – Asu

0
Double min = Arrays.stream(myArray).min(Double::compare).get(); 
Problemi correlati