# Collections.sort klappt nicht



## SolvencyII (25. Mrz 2017)

Hallo!

Eine weitere Frage, die ich habe, bezüglich des gleichen Programms.

Ich will ein Array zweimal nach verschiedenen Spalten sortieren. Nach Country klappt schon mal.

```
List<Flughafen> flughaefen = leseCsvDaten();
        Collections.sort(flughaefen, (a1,a2) -> {return a1.getCountry().compareTo(a2.getCountry());});
```
Jetzt soll es auch noch nach "Airportcode" sortiert werden und daran scheitert es.

```
// Einlesen der Daten in eine map Datenstruktur
        List<Flughafen> flughaefen = leseCsvDaten();
        Collections.sort(flughaefen, (o1,o2) -> {return o1.getAirportcodes().compareTo(o2.getAirportcodes());});
```
Da kriege den Fehler

```
Exception in thread "main" java.lang.NullPointerException
    at FlughafenProjekt.lambda$AirportSuche$1(FlughafenProjekt.java:88)
    at java.util.TimSort.countRunAndMakeAscending(TimSort.java:360)
    at java.util.TimSort.sort(TimSort.java:234)
    at java.util.Arrays.sort(Arrays.java:1512)
    at java.util.ArrayList.sort(ArrayList.java:1454)
    at java.util.Collections.sort(Collections.java:175)
    at FlughafenProjekt.AirportSuche(FlughafenProjekt.java:88)
    at FlughafenProjekt.run(FlughafenProjekt.java:44)
    at FlughafenProjekt.main(FlughafenProjekt.java:25)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

Process finished with exit code 1
```
Hat jemand eine Ahnung woran das liegt? Wäre echt dankbar um einen Tipp/Hilfe.

Gruß, SII


----------



## mrBrown (25. Mrz 2017)

_Vermutlich_ ist `o1.getAirportcodes()` `null`, mehr verrät dir der Debugger oder ein sout




SolvencyII hat gesagt.:


> Ich will ein Array zweimal nach verschiedenen Spalten sortieren


Nein, du willst kein Array nicht nach Spalten sortieren, du willst eine Liste nach Attributen der enthaltenen Objekte sortieren.


----------



## SolvencyII (25. Mrz 2017)

mrBrown hat gesagt.:


> _Vermutlich_ ist `o1.getAirportcodes()[icode] [icode]null`, mehr verrät dir der Debugger oder ein sout
> 
> 
> 
> Nein, du willst kein Array nicht nach Spalten sortieren, du willst eine Liste nach Attributen der enthaltenen Objekte sortieren.


Danke. Stimmt, die Beschreibung ist noch gewöhnungsbedürftig für mich.

Dein Tipp stimmt. Der Airportcode kann "null" bzw. nicht vorhanden sein. Wie kann ich das in meiner lambda expression berücksichtigen? hätte intuitiv o1 und o2 getestet, aber die werden dann ja nicht sortiert...


----------



## mrBrown (25. Mrz 2017)

Entweder selber prüfen, oder die statische Funktionen aus Comparator nutzen, zB `Comparator.nullsFirst`


----------



## SolvencyII (26. Mrz 2017)

mrBrown hat gesagt.:


> Entweder selber prüfen, oder die statische Funktionen aus Comparator nutzen, zB `Comparator.nullsFirst`


Danke für den Tipp. Jetzt muss ich es nur noch in meinen Code einbauen.

Leider hat es aber bei mir nicht geklappt. Ich habe es verschieden ausprobiert, zum Beispiel kriege ich mit dem Code

```
// Einlesen der Daten in eine map Datenstruktur
        List<Flughafen> flughaefen = leseCsvDaten();
        Collections.sort(flughaefen, Comparator.nullsFirst((o1,o2) -> {return o1.getAirportcodes().compareTo(o2.getAirportcodes());}));
```
weiterhin einen Fehler. Meine lambda expression ist ja mein Comparator...daher dachte ich, dass es so klappen muss.


----------



## mrBrown (26. Mrz 2017)

Der nullsFirst-Comparator bekommt jetzt deine Flughäfen übergeben, da würde null vor einem Flughafen einsortiert werden. Flughäfen sind allerdings nicht null, sondern `airportcodes`. Du musst deinen Comparator also so umbauen, dass nullsFirst-Comparator die `airportcodes` übergeben bekommt.

Du machst es dir vermutlich leichter, den Comparator erstmal in eine extra Methode auszulagern (bzw ihn auf dem Java-7 Weg zu implementieren), je nachdem wie gut du mit Lambdas und Methoden-Referenzen klar kommst...


----------



## SolvencyII (26. Mrz 2017)

Danke! Ich habe den Comparator in einer Methode ausgelagert. Es sieht nun so aus

```
public enum Orden implements Comparator<Flughafen> {
        ByAirportcodes {
            public int compare(Flughafen o1, Flughafen o2) {
                if (o1.getAirportcodes() == null && o2.getAirportcodes() == null)
                    return 0;
                if (o1.getAirportcodes() == null)
                    return 1;
                else if (o2.getAirportcodes() == null)
                    return -1;
                return o1.getAirportcodes().compareTo(o2.getAirportcodes());
            }
        }
        }
```
und es klappt. Danke!


----------



## mrBrown (26. Mrz 2017)

Das ganze kann man jetzt noch vereinfachen 


```
public enum Orden implements Comparator<Flughafen> {
        ByAirportcodes {
            public int compare(Flughafen o1, Flughafen o2) {
                  return Comparator.nullsFirst(Comparator.naturalOrder())
                           .compare(o1.getAirportcodes(),o2.getAirportcodes());
        }
    }
```


----------

