# Comparable und Comparator



## HASSUN (1. Mrz 2010)

Hallo zusammen,


Ich hab mich gerade bei euren Forum zum unterschied zwischen Comparable und Comparator eingelesen.
Da stand das falls sich für ein Objekt eine Natürliche Ordnung finden lässt, kann man das Interface jaa.lang.Comparable benutzen. 
Dabei wird der Algorithmus in der Methode compareTo implimentiert um herauszufinden welches der Objekte größer ist.

Sollte sich keine Natürliche Ordnung finden, so wird der Comparator eingesetzt welcher die Methode compare benutzt. Diese vergleicht ebenso zwei Objekte welche größer ist. Comparator wird jedoch bei seltsame Vergleiche gemacht.


Meine Aufgabe die ich habe ist einmal den unterschied zwichen Comparable und Comparator zu definieren und Aufgabe (b) 
Implimentiere einen Comparator, welcher Buch nach Titel und Autor sortiert.

Frage:
Meint man mit einer Natürlichen Ordnung z.B Helligkeit von Licht oder einen Geräusch eines Motors je nachdem welcher lauter ist oder die Stärke von Eisen.

Wie könnte  dann für die Aufgabe (b) eine Ordnung finden lassen nach was sortiert werden soll??


LG


----------



## SlaterB (1. Mrz 2010)

> Wie könnte dann für die Aufgabe (b) eine Ordnung finden lassen nach was sortiert werden soll??

die Ordnung steht doch in der Aufgabe, du sollst sie nur implementieren

---------

'natürliche' zu 'sonstige' Ordnung ist etwas übertrieben interpretiert,
aber es gilt nunmal, dass man das Comparable-Interface nur einmal implementieren kann und dann genau eine bestimmende Ordnung in der Klasse selber definiert,
die Standard-Sortierung, die bei jedem einfachen Collections.sort(liste) verwendet wird,
für Strings und Zahlen z.B. alphabetisch, aufsteigend usw., durchaus die 'natürliche Ordnung'

Comparator sind dagegen beliebige für den Einzelfall neu erstellte Objekte, mit denen man andere Ordnungen definieren kann,
z.B. erstmal nach Länge eines String, Quersumme der Buchstaben und dann noch Vokal vor Konsonant 
sowas komisches will man nicht in der Klasse stehen haben, das macht man getrennt in einem Comparator

es spricht aber technisch nichts dagegen das andersrum zu machen 
oder ein Klase überhaupt nicht Comparable implementieren zu lassen sondern immer nur Comparatoren zu verwenden (wenn man sich nicht willkürlich irgendeinen Standard ausdenken will)


----------



## Landei (1. Mrz 2010)

In meinem eigenen Code versuche ich Comparable zu vermeiden und nur mit Comparatoren zu arbeiten. Die Implementierung des Comparable-Interfaces verträgt sich z.B. schlecht mit Vererbung (wenn relevante Datenfelder hinzugefügt werden). Praktisch ist, häufig gebrauchte Comparatoren als statische Member anzubieten:


```
public class Bla {
   public final static Comparator<Bla> ORDERED_BY_FOO = new Comparator<Bla>() {
     //Implementation...
   };
   public final static Comparator<Bla> ORDERED_BY_BAR = new Comparator<Bla>() {
     //Implementation...
   };
   ...
}
```


----------



## HASSUN1 (1. Mrz 2010)

Dankeschön,


Ich hab mal versucht die Implementierung vorzunehmen, muss aber sagen das ich mich etwas schwer bei dem tue.

mein kleiner Anasatz:


```
// Klasse Buch
Class Buch {

String Titel;
String Autor;


Buch ( String Titel, String Autor ) {

this.Titel = Titel;
this.Autor = Autor;

}


public String getTitel(){ return Titel; }
public String getAutor(){ return Autor; }

}

// Nun muss dann der Comparator erstellt werden, der die Sortierung vor nimmt.
```


Jetzt müsste der Comparator erstellt werden, aber wie könnte der aussehen. Könnte mir jemand einen Ansatz zeigen wie's nun weiter geht.


LG


----------



## SlaterB (1. Mrz 2010)

wie kannst du dich 'eingelesen' haben ohne irgendwelche Beispiele zu kennen,
das wirft man dir doch überall hinterher:
Google


----------



## HASSUN2 (1. Mrz 2010)

Ich denke mal ein Individuelles beispiel hilft mir mehr als die Beispiele aus google. Bei denen es meistens darum geht if ( a > b ) return 1 else if ( a < b ) return -1 else return 0

Bei mein Beispiel gehts aber nicht um Zahlen sondern um etwas anderes. Sortieren nach Titel und Autor. Wenn mir google sowas ausspucken würde, dann würd ich euch nicht fragen und um Hilfe bitten.

Außerdem brauch ich beim pogrammieren bei java etwas hilfe von selbs schaff ich das nicht.
Würd mich also freuen wenn jemand so nett ist und es mit mir schrittweise durchgeht.

LG


----------



## SlaterB (1. Mrz 2010)

dieser Wunsch ist berechtigt, 
von mir noch der Hinweis, dass z.B. schon der erste google-Link keine ints vergleicht, sondern Namen, echte Strings,
du müsstest praktisch nur noch getName() durch getTitle() ersetzen


----------



## HASSUN2 (1. Mrz 2010)

hmmm....
kannst du mir nun wirklich bei der realisation helfen oder nicht.

getTitel durch getName zu ersetzen ist nicht wirklich schwer. Und nun? Comparator Example For User Defined Class : CollectionApache CommonJava das sieht mir sehr kompliziert aus. 


```
// Klasse Buch
Class Buch {

String Titel;
String Autor;


Buch ( String Titel, String Autor ) {

this.Titel = Titel;
this.Autor = Autor;

}


public String getTitel(){ return Titel; }
public String getAutor(){ return Autor; }

}
```


----------



## eRaaaa (1. Mrz 2010)

Naja, du kannst doch aber zu mindestens schon einmal den groben Aufbau gestalten oder nicht?

```
class BookComparator implements Comparator<Buch> {

    @Override
    public int compare(Buch o1, Buch o2) {
	//vergleiche titel
	//titel gleich ? dann vergleiche autor
    }
}
```

o1 und o2 sind die Bücher die du vergleichen willst..du kannst nun auf deren methoden getTitel, getAutor zugreifen. Die geben dir ja einen String zurück...diese Strings musst du nun vergleichen...(Tip: Strings haben eine natürliche Ordnung)!

(ich bin mir auch sicher dass hier im Forum sich das ein oder andere Beispiel zum Vergleich mit Strings finden lässt  )


----------



## SlaterB (1. Mrz 2010)

das wichtigste wäre z.B. schonmal, überhaupt eine Comparator-Klasse zu erstellen,
das kannst du auch von Landei's Posting oben kopieren, die generischen Klammern <Bla> müssen erstmal nicht sein,

das klingt simpel, aber nichtmal diesen Schritt übernimmst du, daher fällt mir nichts zur Hilfe ein,
ich könnte es entweder komplett für dich programmieren, was ich nicht will, oder weiter auf die überall sehr offensichtlichen Vorlagen hinweisen


----------



## HASSUN3 (1. Mrz 2010)

Also Ich würde mal sagen, es müsste so aussehen. Übrigens lassen sich Strings auch mit equals vergleichen aber dein Tipp bezog sich auf eine natürliche Ordnung deswegen habe ich compareTo verwendet.



```
public int comparator implements Comparator<Buch>

@Override
public int compare ( Buch eins, Buch zwei ) {

if ( ein.getTitel().compareTo(zwei.getTitel() ) && ein.getAutor().compareTo(zwei.getAutor() ) ) { return ... } 

}
```


----------



## Landei (1. Mrz 2010)

compareTo liefert ein int (traditionell sollte man bei -1, 0 oder 1 bleiben, muss aber nicht sein).


----------



## SlaterB (1. Mrz 2010)

bei compare gehts doch darum einen int-Rückgabewert zurückzugeben..
dazu fehlt noch alles, immer auf die Beispiele schauen,
ohne return macht eine compare-Methode selbst syntaktisch wenig Sinn, 

----

in einem if gehört compare auch eher weniger, höchstens in der Form

```
if ( ein.getTitel().compareTo(zwei.getTitel()  == 0 )
```
==
WENN die Titel gleich sind DANN.. (dann vergleiche z.B. die Autoren, sonst reicht der Titel-Vergleich)


----------



## eRaaaa (1. Mrz 2010)

noch ein Zusatz

```
public int comparator implements Comparator<Buch>
```

in welchem Beispiel steht das denn so? :>

Vllt. solltest du auch erstmal ein wenig lesen und Theorie aneignen: Galileo Computing :: Java ist auch eine Insel (8. Auflage) – 12.4 Vergleichen von Objekten


----------



## HASSUN4 (1. Mrz 2010)

okAy, so sollte es dann SInn ergeben: 


```
public int comparator implements Comparator<Buch>

@Override
public int compare ( Buch eins, Buch zwei ) {


                int titel = ein.getTitel().compareTo(zwei.getTitel();
                int autor = ein.getAutor().compareTo(zwei.getAutor();
                
                if (titel != 0)
                {
                        return titel;
                }
                else (autor != 0)
                {
                        return autor;
                }

}
```


----------



## SlaterB (1. Mrz 2010)

schon recht gut, fehlt noch der Feinschliff, den kann ich nun ja ergänzen


```
public class BuchComparator implements Comparator<Buch> {

     @Override
     public int compare ( Buch eins, Buch zwei ) {
                int titel = ein.getTitel().compareTo(zwei.getTitel();
                if (titel != 0)
                {
                        return titel;
                }
                return ein.getAutor().compareTo(zwei.getAutor();
    }
}
```
Klasse richtig definieren!

für autor == 0 muss auch etwas zurückgegeben werden


je nachdem ob aufsteigend oder absteigend sortiert werden soll, eins und zwei vertauschen,
auf jeden Fall testen, nicht so für richtig halten


----------



## HASSUN5 (1. Mrz 2010)

Ist dein Beispiel nicht das gleiche wie das hier:
also das man anstatt das: return ein.getAutor().compareTo(zwei.getAutor();
auch das ganze ausschreibt...


```
public class BuchComparator implements Comparator<Buch> {
 
     @Override
     public int compare ( Buch eins, Buch zwei ) {
                int titel = eins.getTitel().compareTo(zwei.getTitel();
                if (titel != 0)
                {
                        return titel;
                }


                int autor = ein.getAutor().compareTo(zwei.getAutor();
                if (autor != 0)
                {
                        return autor;
                } else if ( autor == 0 ){
                    return 0;
                }
		
    }
}
```


----------



## nrg (1. Mrz 2010)

HASSUN5 hat gesagt.:


> Ist dein Beispiel nicht das gleiche wie das hier:



ja, ist im Grunde das Gleiche (nur eben, dass du dir mit Slaters Variante einen int und eine Kontrollstruktur sparst ).


----------



## SlaterB (1. Mrz 2010)

das dürfte das gleiche sein, ja, nur wäre die Variante mit dem if für autor unnötig länger und unschön

edit: ein Unterschied ist noch, dass die zweite Variante nicht kompiliert, da der Kompiler nicht für jede Situation einen Rückgabewert als gesichert sieht


----------



## HASSUN6 (1. Mrz 2010)

Alles klar, also ist die Musterlösung bis hierin:


```
// Klasse Buch
Class Buch {

String Titel;
String Autor;


        Buch ( String Titel, String Autor ) {

         this.Titel = Titel;
         this.Autor = Autor;
        }

 
       public String getTitel(){ return Titel; }
       public String getAutor(){ return Autor; }




public class BuchComparator implements Comparator<Buch> {
 
     @Override
     public int compare ( Buch eins, Buch zwei ) {
                int titel = eins.getTitel().compareTo(zwei.getTitel();
                if (titel != 0)
                {
                        return titel;
                }


                int autor = ein.getAutor().compareTo(zwei.getAutor();
                if (autor != 0)
                {
                        return autor;
                } else if ( autor == 0 ){
                    return 0;
                }
		
    }
}

}
```


Kann ich das jetzt so auf meinen Karteikarten aufschreiben oder ist da noch was Falsch?



Ich danke allen beteiligten für ihre Hilfe!!


----------



## SlaterB (1. Mrz 2010)

SlaterB hat gesagt.:


> edit: ein Unterschied ist noch, dass die zweite Variante nicht kompiliert, da der Kompiler nicht für jede Situation einen Rückgabewert als gesichert sieht




und sowieso:



SlaterB hat gesagt.:


> auf jeden Fall testen, nicht so für richtig halten



--------

Class Buch {
ist auch kein korrekter Java-Code, aber ich werde jetzt nicht weiter jeden Tipp-Fehler anmerken,
schreibe Java-Programme und teste die auch


----------



## Murray (1. Mrz 2010)

HASSUN6 hat gesagt.:


> ```
> if (autor != 0)
> {
> return autor;
> ...


Das lässt sich stark vereinfachen:

```
return autor;
```


----------



## nrg (1. Mrz 2010)

Murray hat gesagt.:


> Das lässt sich stark vereinfachen:


die lösung hatte ihn slater schon gepostet und wurde danach nochmal erklärt aber irgendwie gefällt ihm das nicht


----------

