Sortieren nach Prioritätsgruppen (prioritätsgesteuert)

best-practice

#1

Hallo, passte vielleicht auch in Mathematik. Ich möchte nach drei Kriterien sortieren, der Code bisher bekannt aus anderem Thread hat sich nicht groß geändert:

        for (boolean weiter = true; weiter;) {
            setItems();
            items.sort(new Comparator<Item>() {
                @Override
                public int compare(Item o1, Item o2) {
                    return o1.dauer - o2.dauer;
                }
            });
            for (Item item : items) { /* anstatt der Schleife wähle ich dann einfach erstes item insofern verfügbar */
                if (item.verfuegbar) {
                    click(item.clickable);
                    weiter = true;
                    break;
                } else {
                    weiter = false;
                }
            }
        }

Sortiert werden soll nach:

  1. Verfügbarkeit
  2. Prioritätsgruppe
  3. Dauer

Die Prioritätsgruppen sind so:

String[][] gruppen = {{"a", "b", "c"},
        {"d", "e", "f", "g"},
        {"h", "i", "j"}
        };

D. h., wer mit a,b oder c anfängt, soll eine höhere Priorität haben als wer mit h,i oder j ODER d,e,f oder g anfängt!

Wie muss ich jetzt sortieren? Erst nach dauer, dann nach Prioritätsgruppe und dann nach Verfügbarkeit, richtig? Und wie sieht die Sortierung nach Prioritätsgruppen aus?

Oder gar 'ne PQueue wählen?

Vielen Danke für Input :slight_smile: .

Edit:
Item hat neben dauer und verfuegbar auch ein Attribut name des Typs String.


#2
for (boolean weiter = true; weiter;) {

Geht’s eigentlich noch schlimmer? warum kein

while(true){ 
  /*...*/ 
   if(returnitem.verfuegbar){
   /* ...*/ 
       return; 

in einer eigene Methode?

Die Prioritätsgruppen sind so:

String[][] gruppen = {{"a", "b", "c"},
   {"d", "e", "f", "g"},
   {"h", "i", "j"}
   };

Würde ich ja in eine Map legen:

 Map<String,Integer> gruppen = new HashMap<>();
     gruppen.put("a", 0);
     gruppen.put("b", 0);
     gruppen.put("c", 0);
     gruppen.put("d", 1);
     gruppen.put("e", 1);
     gruppen.put("f", 1);
    //...

der Comparator wäre dann so:

    new Comparator<Item>() {
            @Override
            public int compare(Item o1, Item o2) {
                if(0 != verfuegbarkeitVon(o1)-verfuegbarkeitVon(o2))
                   return verfuegbarkeitVon(o1)-verfuegbarkeitVon(o2);
                if(0!=gruppen.get(o1.getGruppe())-gruppen.get(o2.getGruppe()))
                   return gruppen.get(o1.getGruppe())-gruppen.get(o2.getGruppe());
                return o1.dauer - o2.dauer;
            }
        }

#3

Mit Java 8 hat sich auch bei Comparator etwas getan.

https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#thenComparing-java.util.Comparator-

Comparator<Item> verfuegbarkeitComparator = (Item o1, Item o2) -> verfuegbarkeitVon(o1)-verfuegbarkeitVon(o2);

Comparator<Item> gruppenComparator = (Item o1, Item o2) -> gruppen.get(o1.getGruppe())-gruppen.get(o2.getGruppe());

Comparator<Item> dauerComparator = (Item o1, Item o2) -> o1.dauer - o2.dauer;

Mit diesen Comparatoren, die zum Beispiel auch als static final irgendwo stehen können, kann man sich eine Sortierreihenfolge zusammenbauen. Macht durchaus Sinn, wenn man das später dann auch in einer anderen Reihenfolge sortiert haben möchte.

Comparator<Item> usedComparator = verfuegbarkeitComparator
                                  .thenComparing(gruppenComparator)
                                  .thenComparing(dauerComparator);

#4

Höchstens Java 7 darf ich verwenden.

Ich hab jetzt:

            items.sort(new Comparator<Item>() { // hat viel zu tun
                @Override
                public int compare(Item o1, Item o2) {
                    return o1.dauer - o2.dauer;
                }
            });
            items.sort(new Comparator<Item>() { // hat relativ mäßig zu tun
                @Override
                public int compare(Item o1, Item o2) {
                    return getGruppe(o1.name) - getGruppe(o2.name);
                }
            });
            items.sort(new Comparator<Item>() { // hat fast nix zu tun
                @Override
                public int compare(Item o1, Item o2) {
                    if (o1.verfuegbar && !o2.verfuegbar) {
                        return -1;
                    }
                    if (!o2.verfuegbar && o1.verfuegbar) {
                        return +1;
                    }
                    return 0;
                }
            });

Wie vergleicht man denn Booleans??? (ernsthafte Frage , in C könnte man damit rechnen)

.getGruppe() ist jetzt Implementierungsdetail.

Danke das ihr mich ernstnehmt und nicht wie @Timothy_Truckle einfach abwatscht.

Edit: Ich zeige euch doch .getGruppe()

    private static int getGruppe(String name) {
        String[][] gruppen = {
            {"Darf", "ich", "nicht"},
            {"sagen", "aber", "ist"},
            {"unwichtig"}
        };
        for (int i = 0; i < gruppen.length; i++) {
            for (String item : gruppen[i]) {
                if (name.startsWith(item)) {
                    return i;
                }
            }
        }
        throw new IllegalArgumentException();
    }

#5

Bekomme nen ganz blöde Fehler:

Exception in thread “main” java.lang.NoSuchMethodError: java.util.ArrayList.sort(Ljava/util/Comparator;)V

In dieser Zeile:

items.sort(new Comparator<Item>() { // hat viel zu tun

Kennt er Comparator nicht mehr? :thinking:


Edit: Bitte nicht bemühen, hier steht’s: