allgemein Strings händisch in Liste sortieren

LouCyphre

Bekanntes Mitglied
Hallo,

mal ganz allgemein und Sprachunabhängig. Wie würdet ihr Strings in einer Liste alphanumerisch sortieren (händisch)?

Ich hab mir sowas wie splitten und inseration sort vorgestellt. Eventuell brauch ich ne 2 Liste. . . (Performanz und Speicherkomplexität erstmal hinten angestellt)

Habt ihr eventuell bessere Vorschläge für das Konzept?


Grüße
Lou
 

LimDul

Top Contributor
Grundsätzlich sollte jede Sprache eine Möglichkeit bieten auf einer Liste eine Sortierung mit einem benutzerdefinierten Comparator aufzurufen. Ich verstehe die Frage nicht? Wie sortiere ich eine Liste - in dem ich einen Sortier-Algorithmus (Mergesort, Quicksort, ...) drauf anwende und dabei eine Vergleichfunktion verwende.
 

LouCyphre

Bekanntes Mitglied
Grundsätzlich sollte jede Sprache eine Möglichkeit bieten auf einer Liste eine Sortierung mit einem benutzerdefinierten Comparator aufzurufen.
sicher. aber ich soll es halt selbst implementieren.

verstehe die Frage nicht?
die Frage ist, welcher Algo ist am besten für geeignet.

Zusätzliche Fragen wären noch, ob es generell reicht den kompletten String zu vergleichen oder ob man überhaupt splitten muss...
 

LimDul

Top Contributor
Nimm einen beliebigen Sortier-Algorithmus und setz den um. Für den Vergleich, bau einen alphanumerischen Vergleich der Strings - fertig.
 

mihe7

Top Contributor
Wie würdet ihr Strings in einer Liste alphanumerisch sortieren (händisch)?
Wenn ich auf einem Blatt Papier eine Liste von Namen wie z. B.
Code:
Michael
Christopher
Jessica
Matthew
Ashley
Jennifer
Joshua
Amanda
Daniel
David
habe, dann könnte ich damit beginnen, mit den "kleinsten" Namen zu suchen. Ich fange also mit Michael an, merke mir den als den bislang kleinsten Namen, gehe weiter zu Christopher, stelle fest, dass der kleiner als Michael ist, merke mir somit Christopher als bislang kleinsten Namen usw. Wenn ich alle Namen durch habe, weiß ich, dass Amanda der kleinste Name ist.

Ich streiche also Amanda aus der Liste und schreibe mir den Namen ans Ende meiner bislang leeren, sortierten Liste. Damit wäre der erste Durchgang beendet. Im zweiten Durchgang wäre der kleinste Name dann Ashley, da Amanda schon gestrichen ist. In meiner sortierten Liste stünde: Amanda, Ashley. Den Vorgang wiederhole ich, bis alle Namen gestrichen sind.

Alternativ: statt den Namen zu streichen und in eine neue Liste einzutragen, könnte ich die Namen auch nummerieren. Amanda wäre die 1, Ashley die 2 usw.
 

Neumi5694

Top Contributor
Händisch (auf dem Papier) würde ich wahrscheinlich einen Mix aus Bubble und Insertion Sort verwenden.
Wenn ich's selbst programmieren müsste, würde ich Shell-Sort implementieren, der ist intuitiv und einfach, wenn man erst mal das Prinzip verstanden hat.

In der Praxis würde ich aber lediglich den Comparator schreiben (bei String nicht notwendig, da gibt's das schon) und Collections.sort(...) verwenden, aktuell wird dort - glaub ich - eine Tim-Sort verwendet, der sich sehr gut bewährt hat. Wenn mal was Besseres kommt, bauen sie das dann ein.
 

LouCyphre

Bekanntes Mitglied
Ich habe es bis jetzt mit Quicksort gelöst. Passt auch soweit.
In der Praxis würde ich aber lediglich den Comparator schreiben (bei String nicht notwendig, da gibt's das schon) und Collections.sort(...)
Mal angenommen, es gäbe keinen Comparator, wie würde man das aufziehen, wenn man zum Beispiel nach 'B' sortieren möchte oder nach einem beliebigen Buchstaben oder nach der Länge statt nach Alphabet?

Als Tipp für die Implementierung habe ich -1, 0, 1 bekommen.

Was nach meinen Verständnis nur mit 0(n²) umzusetzen wäre, also ne Art Bubblesort.

Letztlich sollte die Klasse alphanumerisch und nach Länge sortieren können und bestenfalls nichts aus dem Standart verwenden, da ich es nicht in Java machen soll.

Wie gesagt mein jetziger Stand ist das es alphabetisch sortiert, ich könnte aber noch ne Art Comparator gebrauchen, um mit dem gleichen Quicksort auch noch nach Länge/beliebigen Buchstaben sortieren kann
 

mihe7

Top Contributor
Mal angenommen, es gäbe keinen Comparator, wie würde man das aufziehen, wenn man zum Beispiel nach 'B' sortieren möchte oder nach einem beliebigen Buchstaben oder nach der Länge statt nach Alphabet?

Als Tipp für die Implementierung habe ich -1, 0, 1 bekommen.
Sortieren impliziert ja, dass es eine Ordnung gibt. Wie diese zustandekommt, spielt keine Rolle. Am Ende fragst Du also immer: ist x "kleiner" bzw. "größer" (im Sinne der Ordnung) als y.

Wenn ich z. B. eine Ordnung Z < Y < X < ... < B < A festlege, dann ist "Zeppelin" kleiner als "Asphalt" und das Ergebnis ist dann eine alphabetisch absteigend sortierte Liste.

Im Code musst Du also nur die Stelle, an der verglichen wird, ersetzen. Zum Beispiel durch eine compare-Methode, die zwei zu vergleichende Elemente als Parameter erwartet und -1 liefert, falls das erste Element "kleiner" (im Sinner der Ordnung) als das zweie Element ist, +1, falls es sich andersrum verhält und 0, fall die beiden Elemente gleich sind.
 

LouCyphre

Bekanntes Mitglied
um Beispiel durch eine compare-Methode, die zwei zu vergleichende Elemente als Parameter erwartet und -1 liefert, falls das erste Element "kleiner" (im Sinner der Ordnung) als das zweie Element ist, +1, falls es sich andersrum verhält und 0, fall die beiden Elemente gleich sind.
was mich nur noch interessieren würde, was soll den mit den Rückgaben ( -1 0 1) passieren?
also ich hab jetzt quasi jeweils 3 Teillisten die die Elemente dann aufnehmen.
ist das auch so gedacht?
 
K

kneitzel

Gast
was mich nur noch interessieren würde, was soll den mit den Rückgaben ( -1 0 1) passieren?
also ich hab jetzt quasi jeweils 3 Teillisten die die Elemente dann aufnehmen.
ist das auch so gedacht?
Nein, es Du vergleichst zwei Elemente, also z.B. a und b. Wenn beim Compare Aufruf etwas < 0 raus kommt, dann wird a vor b gestellt. Kommt etwas > 0 raus, dann kommt erst b und dann a.
==> So kannst Du also durch Vergleichen von Elementen diese sortieren ... und darum ging es doch.
 

LouCyphre

Bekanntes Mitglied
Das müsste ich dann aber mit 2 Schleifen( verschachtelt) machen oder?

Ich hab vorangehend vergessen, dass ich die Teillisten dann wieder zusammen führe, und dann sind sie ja auch sortiert wovon ich mir ein Laufzeitvorteil verspreche im Vergleich zu den 2 Schleifen
 
K

kneitzel

Gast
Also bezüglich Sortierung gibt es mehrere mögliche Algorithmen. Eine Möglichkeit sind dabei auch zwei Schleifen - siehe z.B. Bubblesort.
 

mihe7

Top Contributor
Hier mal eine naive Sortierung:
Java:
for (int i = 0; i < array.length-1; i++) { // Invariante: alle Elemente 0 bis i-1 sind bereits sortiert
    for (int j = i+1; j < array.length; j++) {
        int reihenfolge = vergleiche(array[i], array[j]);
        if (reihenfolge > 0) { // array[i] ist "größer" als array[j]
            vertausche(array, i,j); // vertausche die beiden Elemente im Array
        }
    }
}
 

LouCyphre

Bekanntes Mitglied
siehe z.B. Bubblesort.
Jap, daran hab ich auch gedacht, allerdings mit der Prämisse O(n²) und Quicksort O mit (n log (n))

Hier mal eine naive Sortierung:
Java:
for (int i = 0; i < array.length-1; i++) { // Invariante: alle Elemente 0 bis i-1 sind bereits sortiert
    for (int j = i+1; j < array.length; j++) {
        int reihenfolge = vergleiche(array[i], array[j]);
        if (reihenfolge > 0) { // array[i] ist "größer" als array[j]
            vertausche(array, i,j); // vertausche die beiden Elemente im Array
        }
    }
}
Und das würde bedeuten If Reihenfolge <= 0 lasse alles wie es ist?

Aber das sieht bei mir Recht ähnlich aus, da bin ich beruhigt
 

mihe7

Top Contributor
Und das würde bedeuten If Reihenfolge <= 0 lasse alles wie es ist?
Logisch. Wenn die Elemente schon in der richtigen Reihenfolge stehen, braucht man daran nichts zu ändern. Der Punkt ist aber die vergleiche-Methode, die -1, 0 oder 1 liefert, je nachdem, ob das erste Element kleiner als, gleich oder größer als das zweite Element ist.
 

Blut1Bart

Bekanntes Mitglied
Naja, weil heute Weihnachten ist, hier mal ein Beispiel, wie man das komplett händisch machen kann:

Java:
import java.util.Arrays;

public class Strings {
    public static int compare(String a, String b) {
        boolean swapped = a.length() > b.length();
        if (swapped) {
            String c = a;
            a = b;
            b = c;
        }
        for (int i = 0; i < a.length(); i++) {
            char c1 = a.charAt(i);
            char c2 = b.charAt(i);
            if (c1 >= 'a' && c1 <= 'z') {
                c1 -= 'a' - 'A';
            }
            if (c2 >= 'a' && c2 <= 'z') {
                c2 -= 'a' - 'A';
            }
            if (c1 != c2) {
                if (swapped) {
                    return c2 - c1;
                } else {
                    return c1 - c2;
                }
            }
        }
        for (int i = 0; i < a.length(); i++) {
            char c1 = a.charAt(i);
            char c2 = b.charAt(i);
            if (c1 != c2) {
                if (swapped) {
                    return c2 - c1;
                } else {
                    return c1 - c2;
                }
            }
        }
        return swapped ? 1 : (a.length() - b.length());
    }

    public static void sort(String[] strings) {
        for (int i = 0; i < strings.length; i++) {
            for (int j = i + 1; j < strings.length; j++) {
                if (compare(strings[i], strings[j]) > 0) {
                    String t = strings[i];
                    strings[i] = strings[j];
                    strings[j] = t;
                }
            }
        }
    }

    public static void main(String[] args) {
        String[] strings = {
                "mueller",
                "Meier",
                "Muelle",
                "Mustermann",
                "Mueller1",
                "Mueller",
                "mUELLER"
        };
        sort(strings);
        System.out.println(Arrays.toString(strings));
    }
}

Ausgabe:
Meier, Muelle, Mueller, Mueller1, mUELLER, mueller, Mustermann

Es wird also alphabetisch sortiert und bei Gleichheit wird die kleingeschriebene Variante nach hinten gestellt. (Ich weiß gerade nicht wie man diese Art der Sortierung nennt...)
 
K

kneitzel

Gast
Wie kommt man dazu, so eine komplexe compareTo Methode zu schreiben? Mit dem tauschen und so ist doch nun wirklich unnötig.

Man geht die Zeichen durch von 0 bis höchstem Index des kürzesten Strings und vergleicht die Zeichen. Sind diese nicht gleich, dann kann man die Differenz zurück geben.
Wenn die Schleife durchlaufen wurde ohne dass ungleiche Zeichen gefunden wurden, dann wird die Differenz der Längen zurück gegeben.

=> kurz, knapp und einfach verständlicher Code. Wenn man sich den Source von String anschaut, dann dürfte man auch genau sowas finden.
 

LouCyphre

Bekanntes Mitglied
=> kurz, knapp und einfach verständlicher Code. Wenn man sich den Source von String anschaut, dann dürfte man auch genau sowas finden.
Ja das sollte ich Mal machen.
Es wird also alphabetisch sortiert und bei Gleichheit wird die kleingeschriebene Variante nach hinten gestellt. (Ich weiß gerade nicht wie man diese Art der Sortierung nennt...)
Danke, aber generell hab ich das verstanden und wie gesagt auch bereits schon implementiert, mir ging es nur noch um den Umgang der Rückgabe Werte.
 

mihe7

Top Contributor
Okay, aber wo finde ich das in deinem Code?
Die Implementierung der vergleiche-Methode? Nirgends, die spielt hier auch keine Rolle. Du wolltest wissen, wie mit den Rückgabewerten umzugehen ist und ich habe Dir ein Beispiel dazu gezeigt. Die Sortierfunktion sortiert anhand der Rückgabewerte der vergleiche-Methode. Die Reihenfolge im Ergebnis wird also durch die vergleiche-Methode bestimmt.

Übrigens: die vergleiche-Methode ist nichts anderes als die compare-Methode eines Comparators ;)
 

Blut1Bart

Bekanntes Mitglied
Mit dem tauschen und so ist doch nun wirklich unnötig
Das ist nicht unnötig:
Es wird also alphabetisch sortiert und bei Gleichheit wird die kleingeschriebene Variante (innerhalb der Variantengruppe) nach hinten gestellt.

Klar, ich hätte auch einfach die Methode von String nehmen können, aber das wäre uninteressant. Es ginge bestimmt auch ohne Vertauschen, ist dann aber nicht mehr so gut lesbar.

Hier nochmal ein Beispiel, anhand dessen alles deutlicher werden sollte:
Java:
    public static void main(String[] args) {
        String[] strings = {
                "AA",
                "Aa",
                "aA",
                "aa",
                "AAA",
                "AAa",
                "AaA",
                "aAA",
                "Aaa",
                "aAa",
                "aaA",
                "aaa"
        };
        sort(strings);
        System.out.println(Arrays.toString(strings));
        // will print:
        // [AA, AAA, AAa, Aa, AaA, Aaa, aA, aAA, aAa, aa, aaA, aaa]
    }

Ich weiß leider wie gesagt nicht wie diese Sortierung genau heißt. Du anscheinend aber auch nicht, sonst hättest du nicht so einen Kommentar abgegeben.

Hier wurde explizit danach gefragt, wie man alles selber umsetzen kann. Manchmal macht das auch Sinn, wenn man zum Beispiel an eingebettete Systeme/Mikrocontroller denkt, bei denen kein Sortierverfahren zur Verfügung steht. Ganze Wörterbücher lassen sich damit natürlich nicht sortieren, denn dafür ist die "sort" Methode zu schlecht... das liegt auf der Hand. :)
 

Meniskusschaden

Top Contributor
Es ginge bestimmt auch ohne Vertauschen, ist dann aber nicht mehr so gut lesbar.
Kannst du auch die Version vor der Obfuskationsphase posten, damit man sich das mal ansehen und eine Meinung darüber bilden kann?;)

Das ist nicht unnötig:
wird also alphabetisch sortiert und bei Gleichheit wird die kleingeschriebene Variante nach hinten gestellt. (Ich weiß gerade nicht wie man diese Art der Sortierung nennt...)
Klar, ich hätte auch einfach die Methode von String nehmen können, aber das wäre uninteressant. Es ginge bestimmt auch ohne Vertauschen, ist dann aber nicht mehr so gut lesbar.
Aber daraus folgt doch höchstens, dass man zweimal vergleichen muss. Das ist doch erst recht ein Grund, es vernünftig lesbar zu gestalten - z.B. gemäß dem Vorschlag von @kneitzel. Er hat doch gar nichts geschrieben, dass nicht in Einklang mit deinen Sortieranforderungen zu bringen ist.
 
K

kneitzel

Gast
Es ginge bestimmt auch ohne Vertauschen, ist dann aber nicht mehr so gut lesbar.
Ok, dann sind wie wieder beim üblichen Punkt, bei dem Du Deine komplexere Version für lesbarer hältst. Ist ok, der Meinung darfst Du sein und ich verzichte diesmal auch auf Argumente. Wer sich ein eigenes Bild machen will, der kann meinen Vorschlag implementieren und den Code vergleichen.
 

Meniskusschaden

Top Contributor
Wer sich ein eigenes Bild machen will, der kann meinen Vorschlag implementieren und den Code vergleichen.
Ich hab's mal gemacht, allerdings mit einer kleinen Abweichung, weil mir bei der Sortierfolge von @Blut1Bart die Position von Mueller1 nicht gefällt. Bei ihm kommt folgendes heraus:
Meier, Muelle, Mueller, Mueller1, mUELLER, mueller, Mustermann
und bei mir dieses Ergebnis:
Meier, Muelle, Mueller, mUELLER, mueller, Mueller1, Mustermann

Java:
    private static int compare(String a, String b) {
        int result = compare(a, b, false);
        return result!=0 ? result : compare(a, b, true);
    }
   
    private static int compare(String a, String b, boolean caseSensitive) {
        for (int i = 0; i<a.length() && i<b.length(); i++) {
            char charA = caseSensitive ? a.charAt(i) : upper(a.charAt(i));
            char charB = caseSensitive ? b.charAt(i) : upper(b.charAt(i));
            if (charA != charB) {
                return charA - charB;
            }
        }
        return a.length() - b.length();
    }
   
    private static char upper(char ch) {
        return (ch >= 'a' && ch <= 'z') ? (char)(ch - 'a' + 'A') : ch;
    }
 

Blut1Bart

Bekanntes Mitglied
damit man sich das mal ansehen und eine Meinung darüber bilden kann?
Hier nochmal ohne "swap" in "compare":
Java:
import java.util.Arrays;

public class Strings {
    public static int compare(String a, String b) {
        final boolean compareAB = a.length() <= b.length();
        final int minLen = compareAB ? a.length() : b.length();
        for (int i = 0; i < minLen; i++) {
            char c1 = a.charAt(i);
            char c2 = b.charAt(i);
            if (c1 >= 'a' && c1 <= 'z') {
                c1 -= 'a' - 'A';
            }
            if (c2 >= 'a' && c2 <= 'z') {
                c2 -= 'a' - 'A';
            }
            if (c1 != c2) {
                if (compareAB) {
                    return c1 - c2;
                } else {
                    return c2 - c1;
                }
            }
        }
        for (int i = 0; i < minLen; i++) {
            char c1 = a.charAt(i);
            char c2 = b.charAt(i);
            if (c1 != c2) {
                if (compareAB) {
                    return c1 - c2;
                } else {
                    return c2 - c1;
                }
            }
        }
        return compareAB ? a.length() - b.length() : 1;
    }

    public static void sort(String[] strings) {
        for (int i = 0; i < strings.length; i++) {
            for (int j = i + 1; j < strings.length; j++) {
                if (compare(strings[i], strings[j]) > 0) {
                    String t = strings[i];
                    strings[i] = strings[j];
                    strings[j] = t;
                }
            }
        }
    }

    public static void main(String[] args) {
        String[] strings = {
                "A",
                "a",
                "",
                "AA",
                "Aa",
                "aA",
                "aa",
                "AAA",
                "AAa",
                "AaA",
                "aAA",
                "Aaa",
                "aAa",
                "aaA",
                "aaa"
        };
        sort(strings);
        System.out.println(Arrays.toString(strings));
        // will print:
        // [, A, AA, AAA, AAa, Aa, AaA, Aaa, a, aA, aAA, aAa, aa, aaA, aaa]
    }
}

Wie man sieht gibt es eine zusätzliche Variable.

Ok, dann sind wie wieder beim üblichen Punkt, bei dem Du Deine komplexere Version für lesbarer hältst.
Könntest du solche Kommentare lassen? Danke. Denn das bringt niemandem etwas. Wenn man es selber nicht kann, dann dürfte man aus meiner Sich gar nicht den Code von anderen bewerten. Leider hat kneitzel aufgrund seiner "Erfahrung" eine Art Narrenfreiheit, worüber man nur den Kopf schütteln kann.

Nochmal: Es bringt absolut nichts, die compareTo Methode von String hier 1:1 wiederzugeben. Deshalb kann er von mir etwas lernen, von euch nicht.
 

Neumi5694

Top Contributor
wie würde man das aufziehen, wenn man zum Beispiel nach 'B' sortieren möchte oder nach einem beliebigen Buchstaben oder nach der Länge statt nach Alphabet?

Als Tipp für die Implementierung habe ich -1, 0, 1 bekommen.

Was nach meinen Verständnis nur mit 0(n²) umzusetzen wäre, also ne Art Bubblesort.

Letztlich sollte die Klasse alphanumerisch und nach Länge sortieren können und bestenfalls nichts aus dem Standart verwenden, da ich es nicht in Java machen soll.

Wie gesagt mein jetziger Stand ist das es alphabetisch sortiert, ich könnte aber noch ne Art Comparator gebrauchen, um mit dem gleichen Quicksort auch noch nach Länge/beliebigen Buchstaben sortieren kann

Hier ein Beispiel für die Stringlänge. Mit berücksichtigt hab ich, ob einer der Werte oder beide null sind.

[CODE lang="java" title="Beispiel für Stringlänge"] public int compare(String o1, String o2) {
if (o1 == null) {
return o2 == null ? 0 : 1;
} else if (o2 == null) {
return -1;
} else {
return Integer.compare(o1.length(), o2.length());
}
}
[/CODE]

Wenn man z.B. Personen nach Vornamen und Namen sortieren will, könnte man das z.B. so machen:

[CODE lang="java" title="Beispiel für Stringlänge"] public int compare(Person o1, Person o2) {
if (o1 == null) {
return o2 == null ? 0 : 1;
} else if (o2 == null) {
return -1;
} else {
int result = o1.getFirstName().aa.compareToIgnoreCase(o2.getFirstName());
if (result != 0) {
return result;
} else {
return o1.getLastName().aa.compareToIgnoreCase(o2.getLastName());
}
}
}
[/CODE]
Wenn du mit Lambda arbeitest, kannst du allerdings auch getrennte Komparatoren für Vor- und Nachnamen schreiben und diese dann aneinanderhängen (thenCompare).
 

Blut1Bart

Bekanntes Mitglied
Der Knackpunkt ist aber, dass man für Strings nicht irgendeinen magischen Wert berechnen kann, anhand dessen man dann vergleichen kann...
 

Neumi5694

Top Contributor
Der Knackpunkt ist aber, dass man für Strings nicht irgendeinen magischen Wert berechnen kann, anhand dessen man dann vergleichen kann...
Eigentlich schon, man muss nur definieren, woraus dieser magische Wert, bzw. das Sortierkriterium besteht. Ohne zu wissen, was das Sortierkriterium ist, könnte man Strings genausogut nach deren Hash-Wert sortieren oder nach der Adresse im Speicher (letztere unterscheidet sich natürlich bei jeder Ausführung des Programms)
 

temi

Top Contributor
Nochmal: Es bringt absolut nichts, die compareTo Methode von String hier 1:1 wiederzugeben. Deshalb kann er von mir etwas lernen, von euch nicht.
Das ist jetzt aber wirklich Unfug. Er weiß nicht, wie man compare implementiert. Damit ist es relativ egal, welche konkreten Code man als Beispiel hier aufführt.

Beim Code der compareTo() Methode von String, kann man sich immerhin darauf verlassen, dass er nicht, benennen wir es vorsichtig, "seltsam" ist.

Da die Java-Bibliotheken natürlich auch noch weitere Dinge beachten müssen, kann es schon sein, dass der Code dort etwas umfangreicher ist, aber der Kern von compareTo() ist z. B. dieses:
Java:
    public static int compareTo(byte[] value, byte[] other, int len1, int len2) {
        int lim = Math.min(len1, len2);

        for(int k = 0; k < lim; ++k) {
            if (value[k] != other[k]) {
                return getChar(value, k) - getChar(other, k);
            }
        }

        return len1 - len2;
    }

EDIT: Entscheidender ist allerdings, zu verstehen (und in der Doku zu lesen), was die compare Methode von einem verlangt. Letztlich legt man durch die Implementierung selbst selbst fest, wie die Reihenfolge aussehen soll. Was im Übrigen der Sinn des ganzen ist, eine Möglichkeit zu schaffen, für Mengen von eigenen Typen eine spezifische Sortierung zu ermöglichen.
 
Zuletzt bearbeitet:

Blut1Bart

Bekanntes Mitglied
weil mir bei der Sortierfolge von @Blut1Bart die Position von Mueller1 nicht gefällt.
@Meniskusschaden hat Recht, da ist ein Fehler oder eine Inkonsistenz in meiner Variante:
Java:
import java.util.Arrays;

public class Strings {
    public static int compare(String a, String b) {
        final boolean compareAB = a.length() <= b.length();
        final int minLen = compareAB ? a.length() : b.length();
        for (int i = 0; i < minLen; i++) {
            char c1 = a.charAt(i);
            char c2 = b.charAt(i);
            if (c1 >= 'a' && c1 <= 'z') {
                c1 -= 'a' - 'A';
            }
            if (c2 >= 'a' && c2 <= 'z') {
                c2 -= 'a' - 'A';
            }
            if (c1 != c2) {
                if (compareAB) {
                    return c1 - c2;
                } else {
                    return c2 - c1;
                }
            }
        }
        for (int i = 0; i < minLen; i++) {
            char c1 = a.charAt(i);
            char c2 = b.charAt(i);
            if (c1 != c2) {
                if (compareAB) {
                    return c1 - c2;
                } else {
                    return c2 - c1;
                }
            }
        }
        return compareAB ? a.length() - b.length() : 1;
    }

    public static void sort(String[] strings) {
        for (int i = 0; i < strings.length; i++) {
            for (int j = i + 1; j < strings.length; j++) {
                if (compare(strings[i], strings[j]) > 0) {
                    String t = strings[i];
                    strings[i] = strings[j];
                    strings[j] = t;
                }
            }
        }
    }

    public static void main(String[] args) {
        String[] strings = {
                "mueller",
                "Meier6",
                "Meier",
                "Muelle",
                "Mustermann",
                "Mueller1",
                "Mueller",
                "mUELLER"
        };
        sort(strings);
        System.out.println(Arrays.toString(strings));
        // will print:
        // [Mueller, Meier, Meier6, Muelle, Mustermann, mUELLER, Mueller1, mueller] (!!)
    }
}

Wenn man noch Meier6 hinzufügt, dann steht Mueller1 viel zu weit hinten... Das ist mir anfangs nicht aufgefallen, vielen Dank dafür.
 

Meniskusschaden

Top Contributor
Du hast drei Methoden eingeführt. Jetzt könnte man sich auch wieder darüber streiten, was lesbarer sei.
Minimale Methodenanzahl als Entwurfsziel? Hach, das ist so schön retro. Hatte ich das letzte Mal beim HP-41. Der hatte nur einen festen Call-Stack für maximal sechs Aufrufebenen von Unterprogrammen. Ja ja, so war das damals in den Achtzigern. ;)
 
K

kneitzel

Gast
Könntest du solche Kommentare lassen? Danke. Denn das bringt niemandem etwas. Wenn man es selber nicht kann, dann dürfte man aus meiner Sich gar nicht den Code von anderen bewerten. Leider hat kneitzel aufgrund seiner "Erfahrung" eine Art Narrenfreiheit, worüber man nur den Kopf schütteln kann.
Also eigentlich wollte ich diese Diskussion wirklich nicht, aber da hier auch Anfänger über diesen Thread kommen, werde ich mal wieder Argumente bringen. (Etwas, das ich auch von Dir erwarten würde, aber da kommt ja leider nie etwas wirklich brauchbares - was dann eben genau zu solchen Kommentaren führt! Dann bring doch einfach Argumente für Deine Behauptungen statt nur auf Deiner Position zu beharren!)

Aber behandeln wir ein paar Punkte, die hier angesprochen wurden:

Warum Code aufteilen in mehrere Methoden?
- Zum einen ist dies eine einfache Form der Dokumentation. Das wird schnell deutlich, wenn ich einfach einen Code nehme und diesen kommentiere:
Java:
// c1 to upper char
if (c1 >= 'a' && c1 <= 'z') {
    c1 -= 'a' - 'A';
}
Und das mache ich jetzt zu eine Methode - natürlich wären hier jetzt noch Refactorings sinnvoll, aber die lasse ich komplett weg. Wie so eine Methode aussehen könnte, wurde ja schon gezeigt.
Java:
char toUpperChar(char c1) {
    if (c1 >= 'a' && c1 <= 'z') {
        c1 -= 'a' - 'A';
    }   
    return c1;
}
==> Der Bezeichner der Methode dient somit direkt der Dokumentation. Die Methode besagt genau, was denn in der Methode gemacht wird.

- Übersichtlichkeit: Je kleiner die Methode, desto leichter lässt sich diese überblicken. Und desto leichter findet man Fehler. Speziell, wenn man dann zu dem Schritt kommen sollte, dass man Unit Tests schreibt, wird man es so deutlich leichter haben, Methoden vollständig zu testen.

- Doppelten Code vermeiden! Auch hier ist das Beispiel von @Blut1Bart top: Den Code mit dem Umwandeln hat er zwei mal hintereinander. Doppelter Code! Das ist blöd, wenn es um Anpassungen geht. Da muss man dann bei einer Anpassung an mehreren Stellen anpassen. Daher vermeidet man sowas. Bei so einfachen Codes mag man noch drüber hinweg sehen wollen, aber dies ist ein Prinzip, das sehr wichtig ist.

- KISS: Keep it simple, stupid: Eines der Prinzipien von Clean Code. Statt also einer komplexeren Methode hat man lieber mehrere, einfache, "dumme" Methoden.

Wieso ist es unproblematisch, mehr Methoden zu haben?

Es gibt immer wieder Leute, die meinen, etwas auf Resourcen optimieren zu wollen. Ein Methodenaufruf kommt mit einem Overhead daher was die CPU angeht und es wird Speicher auf dem Stack verbraucht. Da könnte man dann tatsächlich meinen, dass sowas Sinn machen könnte.

- Optimierungen macht man nicht! (Oder für die Experten: Noch nicht!). Zum einen wird etwas optimiert, bei dem unklar ist, ob dies überhaupt optimiert werden muss. Ich erkaufe mir also etwas mit schlechter lesbaren Code von dem unklar ist, ob ich es brauche. Daher macht man es nicht. Sollte sich heraus stellen, dass ich es doch brauche (Speicherprobleme, zu lange Laufzeiten, Stack Overflow, ...), dann bringt es nichts, blind zu optimieren. Statt dessen wird dann erst einmal analysiert, was denn das Problem ist. Ein Stack Overflow kommt in erster Linie bei Rekursiven Aufrufen vor. Da wäre es also zielführender, an so einer Stelle etwas zu drehen. Wenn etwas zu lange läuft, dann sind die Probleme meist nicht ein Methodenaufruf (Komplexität O(1)) sondern die Komplexität eines Algorithmus. Da sollte man also ggf. den Algorithmus anpassen. Also immer erst das Problem analysieren um es dann zu lösen.

An der Stelle einfach einmal überlegen, wie sehr ein Methodenaufruf in einer rekursiven Methode den Stack belastet. Also angenommen dieses toUpperCase würde in einer Methode aufgerufen, die sich selbst rekursiv aufruft. Die Belastung des Stacks ist 1 Aufruf. Denn toUpperCase wird aufgerufen (Stack wird belastet) um sich dann nach dem Umwandeln direkt zu beenden (Stack wird wieder entlastet).

- Optimierungen werden schon an anderer Stelle durchgeführt!
Viele Dinge können automatisch deutlich besser optimiert werden! So optimiert der Java Compiler und der JIT Compiler. Es kann also sein, dass die Methode, die wir geschrieben haben, eh schon als Code eingegliedert wurde.

Auf Bezeichner achten!

Aus meiner Sicht ist es wichtig, auf Bezeichner zu achten. Ich frage mich immer, wie Leute auf die Idee kommen, Variablen immer mit Ax zu bezeichnen mit A Element aus [a-z] und x Element aus [0-9]. Was bitte ist c1? c2? a? b? Die Variablen sagen nichts aus. Das mag in einem engen Kontext ok sein, aber dann muss der Kontext auch wirklich sehr eng gefasst sein. (Also wieder: kurze, kleine Methoden!) Aber besser ist es immer, wenn die Bezeichner aussagen, was enthalten ist.

Links

Natürlich geht das alles nicht auf mich zurück. Ich habe mir dies auch nur "geklaut".

Clean Code Developers
Eine Seite, in der Neulinge an Clean Code heran geführt werden sollen. Es wird hier mit Graden gearbeitet, so dass man einzelne Punkte nach und nach dazu nimmt. Finde ich sehr gut, da man so nicht gleich erschlagen wird.

Uncle Bob
Uncle Bob (Robert C. Martin) ist einer derjenigen, die sehr stark im Bereich Agiler Entwicklung und Clean Code mitgewirkt haben. Er hat mehrere Bücher zu dem Thema gehalten und hält auch viele Vorträge. Letztere sind auch auf YouTube und ich habe mir erlaubt, diese zu verlinken.

SOLID Principles
Eine der wichtigsten Grundlagen sind die SOLID Principles. Finden sich natürlich auch schon in den ersten Links, aber diese "Basis" muss dennoch auch separat erwähnt werden.

Das einfach einmal an dieser Stelle zur Erläuterung meiner Position. Ich hoffe, dass ich die Punkte deutlich machen konnte. Sollte noch etwas unklar geblieben sein oder ein wichtiger Punkt nicht behandelt worden sein, so bitte ich um eine kleine Information und ich würde dann noch weiter ergänzen (So das nicht eh schon von Anderen ergänzt wird!)
 

Blut1Bart

Bekanntes Mitglied
Jetzt bin ich sehr verwirrt. Ist es so richtig?
Java:
import java.util.Arrays;
import java.util.function.Function;

public class Strings {
    public static char toUpperCaseIfRegularCharacter(char c) {
        if (c >= 'a' && c <= 'z') {
            c -= 'a' - 'A';
            System.out.println("c = " + c);
        }
        return c;
    }

    public static char identityCharacter(char c) {
        return c;
    }

    public static char neutralCharacter(char c) {
        return 'A';
    }

    public static boolean greater(int c) {
        return c > 0;
    }

    public static boolean greaterOrEqual(int c) {
        return c >= 0;
    }

    public static int compare1(String a, String b, Function<Character, Character> wrapper) {
        final boolean compareAB = a.length() <= b.length();
        final int minLen = compareAB ? a.length() : b.length();
        for (int i = 0; i < minLen; i++) {
            char c1 = a.charAt(i);
            char c2 = b.charAt(i);
            if (wrapper.apply(c1) != wrapper.apply(c2)) {
                return c1 - c2;
            }
        }
        return 0;
    }

    public static int compare(String a, String b, Function<Character, Character> wrapper, boolean respectLength) {
        int c = compare1(a, b, wrapper);
        if (c != 0) {
            return c;
        }
        if (!respectLength) {
            return 0;
        }
        return a.length() - b.length();
    }

    public static void sort(String[] strings, Function<Character, Character> wrapper, boolean respectLength, Function<Integer, Boolean> acceptor) {
        // bubble sort:
        for (boolean sorted = false; !sorted; sorted = true) {
            for (int j = 0; j < strings.length - 1; j++) {
                if (acceptor.apply(compare(strings[j], strings[j + 1], wrapper, respectLength))) {
                    String t = strings[j];
                    strings[j] = strings[j + 1];
                    strings[j + 1] = t;

                    sorted = false;
                }
            }
        }
    }

    public static void sort(String[] strings) {
        sort(strings, Strings::neutralCharacter, true, Strings::greater);
        sort(strings, Strings::identityCharacter, false, Strings::greater);
        sort(strings, Strings::toUpperCaseIfRegularCharacter, true, Strings::greater);
    }

    public static void main(String[] args) {
        String[] strings = {
                "mueller",
                "Meier6",
                "M",
                "007",
                "Meier",
                "Muelle",
                "Mustermann",
                "Mueller1",
                "Mueller",
                "mUELLER"
        };
        sort(strings);
        System.out.println(Arrays.toString(strings));
        // will print:
        // [007, M, Meier, Meier6, Muelle, Mueller, mUELLER, Mueller1, mueller, Mustermann] (?)
    }
}

Die Ausgabe ist: 007, M, Meier, Meier6, Muelle, Mueller, mUELLER, Mueller1, mueller, Mustermann

Ich bin mir nicht sicher, ich glaube, weil Comparator chaining bei dieser speziellen Sortierung nicht funktioniert, muss man mehrmals sortieren...

Im Lexikon steht doch auch Aal vor Aachen? 🤔
 

Blut1Bart

Bekanntes Mitglied
🤦‍♂️ 🤦‍♀️ 🤦‍♂️

Manchmal bin ich dumm wie eine Nuss. Da war ein Fehler im Bubblesort:

Java:
        // bubble sort:
        boolean sorted = false;
        while (!sorted) {
            sorted = true;
            for (int j = 0; j < strings.length - 1; j++) {
                if (acceptor.apply(compare(strings[j], strings[j + 1], wrapper, respectLength))) {
                    String t = strings[j];
                    strings[j] = strings[j + 1];
                    strings[j + 1] = t;
                    sorted = false;
                }
            }
        }

Richtigerweise muss dann dreimal sortiert werden:
Java:
    public static void sort(String[] strings) {
        sort(strings, Strings::neutralCharacter, true, Strings::greater);
        sort(strings, Strings::identityCharacter, false, Strings::greater);
        sort(strings, Strings::toUpperCaseIfRegularCharacter, false, Strings::greater);
    }
 

Blut1Bart

Bekanntes Mitglied
@Meniskusschaden Jetzt dürftest auch du zufrieden sein:

Java:
import java.util.Arrays;
import java.util.function.Function;

public class Strings {
    public static char toUpperCaseIfRegularCharacter(char c) {
        if (c >= 'a' && c <= 'z') {
            c -= 'a' - 'A';
            System.out.println("c = " + c);
        }
        return c;
    }

    public static char identityCharacter(char c) {
        return c;
    }

    public static char neutralCharacter(char c) {
        return 'A';
    }

    public static int compare1(String a, String b, Function<Character, Character> wrapper) {
        final boolean compareAB = a.length() <= b.length();
        final int minLen = compareAB ? a.length() : b.length();
        for (int i = 0; i < minLen; i++) {
            char c1 = wrapper.apply(a.charAt(i));
            char c2 = wrapper.apply(b.charAt(i));
            if (c1 != c2) {
                return c1 - c2;
            }
        }
        return 0;
    }

    public static int compare(String a, String b, Function<Character, Character> wrapper, boolean respectLength) {
        int c = compare1(a, b, wrapper);
        if (c != 0) {
            return c;
        }
        if (respectLength) {
            return a.length() - b.length();
        }
        return 0;
    }

    public static void sort(String[] strings, Function<Character, Character> wrapper, boolean respectLength) {
        // bubble sort:
        boolean sorted = false;
        while (!sorted) {
            sorted = true;
            for (int j = 0; j < strings.length - 1; j++) {
                if (compare(strings[j], strings[j + 1], wrapper, respectLength) > 0) {
                    String t = strings[j];
                    strings[j] = strings[j + 1];
                    strings[j + 1] = t;
                    sorted = false;
                }
            }
        }
    }

    public static void sort(String[] strings) {
        sort(strings, Strings::neutralCharacter, true);
        sort(strings, Strings::identityCharacter, false);
        sort(strings, Strings::toUpperCaseIfRegularCharacter, false);
    }

    public static void main(String[] args) {
        String[] strings = {
                "mueller",
                "Meier6",
                "M",
                "007",
                "",
                "Meier",
                "Muelle",
                "Mustermann",
                "Mueller1",
                "Müller",
                "MÜller",
                "Mueller",
                "mUELLER"
        };
        sort(strings);
        System.out.println(Arrays.toString(strings));
        // will print:
        // [, 007, M, Meier, Meier6, Muelle, Mueller, Mueller1, mUELLER, mueller, Mustermann, MÜller, Müller]
    }
}

Btw könnt ihr auch in Code-Tags nicht mehr scrollen?
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
D Chat GPT allgemein und in Bezug auf Softwareentwicklung Allgemeine Java-Themen 105
L MergeSort allgemein Allgemeine Java-Themen 61
K Best Practice JFrame Objekt allgemein zugänglich machen Allgemeine Java-Themen 8
chuxXo BasicPlayer - Beendigung Abfragen (Allgemein) Allgemeine Java-Themen 21
J Allgemein gültige Klasse/Methode mehrfach verwenden Allgemeine Java-Themen 11
F Huffman Allgemein Allgemeine Java-Themen 1
G allgemein synchroniszed verständnisfrage Allgemeine Java-Themen 19
J Client Allgemein Allgemeine Java-Themen 10
M Frage zum Design :: allgemein Allgemeine Java-Themen 6
S Frage zu jTDS, JAVA allgemein und Timer Allgemeine Java-Themen 6
O regulärer Ausdruck zum durchsuchen eines Strings verwenden Allgemeine Java-Themen 2
B HeapSort für Array of Strings funktioniert nur teilweise Allgemeine Java-Themen 3
W JSON parsen eines ,mit JS.stringify erstellten Strings Allgemeine Java-Themen 27
N MySQL mit Strings Allgemeine Java-Themen 3
T Letztes Zeichen eines Strings enfernen Allgemeine Java-Themen 14
P Strings: equals vs == Allgemeine Java-Themen 47
G Objekte mit Strings Aufrufen Allgemeine Java-Themen 8
W Collections Suche Collection, um Strings mit Indizees versehen Allgemeine Java-Themen 47
V Datentypen Graphikrechner 2/Strings und Variablen in Doubles umwandeln Allgemeine Java-Themen 6
LimDul Mittels Streams aus Strings A B C den String A, B und C machen Allgemeine Java-Themen 12
Meeresgott Best Practice Strings auf Inhalte vergleichen Allgemeine Java-Themen 1
N DNA Strings vergleichen Allgemeine Java-Themen 1
Q-bert Strings aus der JList in eine Datenbank speichern Allgemeine Java-Themen 1
K Vergleich von Strings von Objekten Allgemeine Java-Themen 4
J Strings int textdokumente speicher Allgemeine Java-Themen 3
KeVoZ_ Nacheinander folgende Strings in Textdokument auf neue Zeile schreiben Allgemeine Java-Themen 6
K Strings sortieren: 2 Kritieren Allgemeine Java-Themen 5
A Vector Strings in Array splitten Allgemeine Java-Themen 6
B Wie vergleiche ich Strings in einer Liste? Allgemeine Java-Themen 5
T Strings über Bluetooth zwischen PC,µc oder Samrtphone senden und empfangen Allgemeine Java-Themen 0
N Methoden Methoden einer Klasse auf Grundlage eines Strings aufrufen Allgemeine Java-Themen 6
K Bestimmten Bereich eines Strings lesen Allgemeine Java-Themen 6
H RegularExpression zwischen zwei Strings Allgemeine Java-Themen 2
Neumi5694 Operatoren regEx für das Erstellen eines Strings verwenden Allgemeine Java-Themen 3
H Strings vergleichen Allgemeine Java-Themen 9
O Mustererkennung in Strings Allgemeine Java-Themen 4
Y String-Collection: längste gemeinsame Strings / Prefixe Allgemeine Java-Themen 3
F Problem mit Strings Allgemeine Java-Themen 8
D Strings chemisch splitten Allgemeine Java-Themen 3
K Wörter in Strings zählen Allgemeine Java-Themen 7
L Strings nach sortiertem String zurück ordnen Allgemeine Java-Themen 0
L Strings nach gleichem Muster ordnen Allgemeine Java-Themen 4
L Fragen für Facharbeit: Analyse von Strings in Java Allgemeine Java-Themen 4
D Strings vergleichen; Komma ignorieren Allgemeine Java-Themen 3
K Java Operatoren mit Strings darstellen Allgemeine Java-Themen 8
G Strings erzeugen Allgemeine Java-Themen 20
B HTML Tags in Strings umwandeln Allgemeine Java-Themen 4
N Input/Output Vergleich von identischen Strings schlägt fehl Allgemeine Java-Themen 5
U Große Liste von Strings mit indiziertem Zugriff Allgemeine Java-Themen 31
A ,,Textformatierungsbefehle" für strings deaktivieren Allgemeine Java-Themen 8
S Strings vergleichen Allgemeine Java-Themen 11
C Strings in Excel einlesen! Allgemeine Java-Themen 2
S Strings gehen "kaputt" wenn ich in CVS ein und wieder auschecke. Allgemeine Java-Themen 2
X Datentypen Prozentualer Abgleich zwischen 2 Strings (Pattern?) Allgemeine Java-Themen 3
R MD5-Hash eines Strings bestimmen Allgemeine Java-Themen 2
C Strings und JSON Objekte so klein wie möglich im Speicher ablegen Allgemeine Java-Themen 5
J String zerlegen in einzelne Strings Allgemeine Java-Themen 7
F Konstanten mir Strings "verknuepfen" Allgemeine Java-Themen 10
1 zwei Strings vergleichen Allgemeine Java-Themen 16
L Object Instanz anhand eines Strings Allgemeine Java-Themen 10
S vector & strings Allgemeine Java-Themen 26
N Strings mit null wiedergabe Splitten Allgemeine Java-Themen 4
K Strings sortieren (knifflig) Allgemeine Java-Themen 7
P Codierung der strings umändern Allgemeine Java-Themen 10
N Zahlen in Strings einer ArrayList sortieren Allgemeine Java-Themen 14
F 2 Strings zusammenfügen Allgemeine Java-Themen 2
D Strings von HTML befreien Allgemeine Java-Themen 17
S Strings zu Color-Instanzen parsen? Allgemeine Java-Themen 7
C Strings zwischen 2 Zeichen auslesen Allgemeine Java-Themen 7
T Explizite Typkonversation mit Strings Allgemeine Java-Themen 9
R Locale spezifische DateFormat Strings? Allgemeine Java-Themen 3
M Wie kann ich alle System.out Strings in ein log window umleiten? Allgemeine Java-Themen 6
R Java function die Strings escaped, sodass ich sie in Javascript verwenden kann? Allgemeine Java-Themen 4
ruutaiokwu objektreferenz eines strings... Allgemeine Java-Themen 9
data89 [Kurze Frage] Ähnlichkeit zweier Strings ermitteln Allgemeine Java-Themen 19
S bestimmte Strings spliten! Allgemeine Java-Themen 7
M Warum Strings mit equals vergleichen... Allgemeine Java-Themen 6
Daniel_L Suche nach ganzen Wörtern (wholeword) in Strings? Allgemeine Java-Themen 4
A Strings joinen, Standard-Library? Allgemeine Java-Themen 9
Y Mal wieder vergleichen von Strings.[Leider noch ein Problem] Allgemeine Java-Themen 18
data89 Die Größe eines Strings in Byte berechnen? Allgemeine Java-Themen 12
A Auslesen von Strings aus einer xls-Datei Allgemeine Java-Themen 16
G Spezialfrage zu Strings Allgemeine Java-Themen 11
C Textteile aus Strings extrahieren? Allgemeine Java-Themen 6
J Teile eines Strings ersetzen Allgemeine Java-Themen 2
G schnell Strings vergleichen Allgemeine Java-Themen 4
J Name eines Strings durch einen String festlegbar? Allgemeine Java-Themen 2
G Strings zerlegen und substrings auslesen Allgemeine Java-Themen 2
Z Letztes zeichen eines strings löschen Allgemeine Java-Themen 3
V Speicherplatz eines Strings? Allgemeine Java-Themen 12
H MIDlets und Strings Allgemeine Java-Themen 2
C Pixelanzahl eines Strings ermitteln Allgemeine Java-Themen 12
T Strings darf nur Ziffern, +/- haben Allgemeine Java-Themen 9
A Fehler beim Ersetzen eines Strings Allgemeine Java-Themen 3
G Strings die Zahlen enthalten sinnvoll sortieren (A2 < A10 Allgemeine Java-Themen 4
G byte[] mit Strings füllen Allgemeine Java-Themen 2
H strings in datei verschlüsseln , auslesen mit klartext aber! Allgemeine Java-Themen 2
F Strings in JList ausrichten/links/rechts/mittig Allgemeine Java-Themen 10
M String#equals(), Probleme mit großen Strings? Allgemeine Java-Themen 4
H ein Teil des Strings rausfiltern Allgemeine Java-Themen 8

Ähnliche Java Themen

Neue Themen


Oben