Collections Java Wörter in String zählen und geordnet ausgeben

Braniac92

Mitglied
Hey Leute,

Ich würde gerne aus einem String zählen wieoft ein Wort vorkommt und dann Sortiert die 10 häufigsten Wörter rausgeben.

Der String ist folgendermaßen aufgebaut:

String s = "a, b, a, b, c, d, c, a";

Nun suche ich eine Möglichkeit aus diesem zu zählen wie oft ein Wort vorkommt und dann zurückzugeben, wieoft ein Wort vorkommt.
Also etwas ind er Art:

a = 3, b = 2, c = 2, d = 1

Welche Strategie würde sich dafür am besten eignen? Oder gibt es schon funktionen, die das machen?
Wäre für Hilfe sehr dankbar.
 
Mappen würd ich eigentlich nicht im eigentlichen Sinne:
Java:
        int[] array = new int[256];
        String s = "a, b, a, b, c, d, c, a";
        for (int i = 0; i < s.length(); i += 3) {
            array[s.charAt(i)]++;
        }
        for (int i = 0; i < array.length; i++) {
            if (array[i] > 0) {
                System.out.println((char) i + " " + array[i]);
            }
        }

Code:
a 3
b 2
c 2
d 1

Könntet Ihr mir bitte die Java 8 - 9 Lösung geben / zeigen? (Lambda/Funktional) Bin da etwas schwerfällig
 
Ok vielen Dank schonmal.

Ich hab mir das Vorgehen so überlegt.

1) Ich splitte den String beim komma und erhalte dann ein Stringarray mit allen Wörtern.
2) Erstelle mit eine neue Klasse "Player" die die Werte String und In übergeben bekommen.
3) ich erstelle linkedList<Player> in der ich dann sowohl den Namen als auch die Zahl übergebe
4) Dann gehe ich für jedes Wort eine Schleife durch (prüfe vorher schon ab, ob ich das Wort schon geprüft habe, zähle über die Wörte und füge sie als neuen "Player" in die Liste hinzu.
5) Wenn ich fertig bin sortiere ich die Liste nach den Int werten (nur wie?) und dann habe ich mein ergebnis.

Ist dieses Vorgehen gut? Bzw mache ich mir damit zuviel Arbeit?

EDIT: Ok das Wie habe ich.. habe über Collections.sort sortiert. Nun eher die Frage, ob das Vorgehen so sinnvoll ist oder ich es auch hätte "besser" lösen können.
 
Zuletzt bearbeitet:
Also ich möchte Wörter nach Zahlen sortieren. folgende Umsetzung müsste funktionieren:

Java:
LinkedList<Player> p = new LinkedList<Player>();
        p.add(new Player("a", 10));
        p.add(new Player("b", 2));
        p.add(new Player("c", 6));
        p.add(new Player("d", 1));
        p.add(new Player("e", 7));

        System.out.println(p);
       
        Collections.sort(p, new Comparator<Player>(){
               @Override
               public int compare(Player o1, Player o2){
                    if(o1.getTore() < o2.getTore()){
                       return 1;
                    }
                    if(o1.getTore() > o2.getTore()){
                       return -1;
                    }
                    return 0;
               }
            });
       
   
        System.out.println(p);

Kurze Erklärung dazu:
Ein Player besteht aus einem Wort und einer Zahl.
Bei der Collections habe ich 1 und -1 vertauscht, um eine reverseSortierte Liste zuerhalten. So bekomme ich an erster Stelle das Wort mit der höchsten Anzahl.
 
1) Ich splitte den String beim komma und erhalte dann ein Stringarray mit allen Wörtern.

- korrekt. Der Delimiter wäre ", "

2) Erstelle mit eine neue Klasse "Player" die die Werte String und In übergeben bekommen.

- korrekt, der bekommt einen Split

3) ich erstelle linkedList<Player> in der ich dann sowohl den Namen als auch die Zahl übergebe

- könnte man so machen, um erst einmal alle Splits und Zahlen zu sammeln

4) Dann gehe ich für jedes Wort eine Schleife durch (prüfe vorher schon ab, ob ich das Wort schon geprüft habe, zähle über die Wörte und füge sie als neuen "Player" in die Liste hinzu.

- dann wird die Liste ja endlos - und das Programm hält nicht an

5) Wenn ich fertig bin sortiere ich die Liste nach den Int werten (nur wie?) und dann habe ich mein ergebnis.

- was stellen denn die Zahlen für Daten dar???

Java:
/**
*
* @author
*/
public class StringsAufteilen {

    public static void main(String[] args) {
        String s = "a, b, a, b, c, d, c, a";
        String[] split = s.split(", ");
        StringUndZahl[] suz = new StringUndZahl[split.length];
        for (int i = 0; i < split.length; i++) {
            suz[i] = new StringUndZahl();
            suz[i].s = split[i];
        }

        for (String string : split) {
            for (StringUndZahl stringUndZahl : suz) {
                if (string.equals(stringUndZahl.s)) {
//                    for (StringUndZahl stringUndZahl1 : suz) {
//                        if (string.equals(stringUndZahl1.s)) {
//                            stringUndZahl1.i++;
//                        }
//                    }
                    stringUndZahl.i++;
                }
            }
        }

        Arrays.sort(suz, new Comparator<StringUndZahl>() {
            @Override
            public int compare(StringUndZahl o1, StringUndZahl o2) {
                return o2.i - o1.i; // nicht so machen
            }
        });
        for (StringUndZahl stringUndZahl : suz) {
            System.out.println(stringUndZahl);
        }
    }
}

class StringUndZahl {

    String s;
    int i;

    @Override
    public String toString() {
        return "StringUndZahl{" + "s=" + s + ", i=" + i + '}';
    }
}


Code:
StringUndZahl{s=a, i=3}
StringUndZahl{s=a, i=3}
StringUndZahl{s=a, i=3}
StringUndZahl{s=b, i=2}
StringUndZahl{s=b, i=2}
StringUndZahl{s=c, i=2}
StringUndZahl{s=c, i=2}
StringUndZahl{s=d, i=1}
Das würd mir mein Chef um die Ohren haun.

(Zusätzlich: Bitte SSCCE...)
 
Wenn man schonmal was von modernem Java gesehen hat…
Java:
import java.util.Comparator;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class CountWords {

    public static void main(String[] args) {
        String s = "a, b, a, b, c, d, c, a, d, d, d,, , d";

        Stream.of(s.split(","))
                //Strings zuschneiden und leere Strings entfernen
                .map(String::trim).filter(str -> !str.isEmpty())

                //Histogram erstellen
                .collect(Collectors.groupingBy(Function.identity(),
                        Collectors.mapping(i -> 1, Collectors.summingInt(sum -> sum.intValue()))))

                //Einträge nach Anzahl absteigend sortieren
                .entrySet().stream()
                .sorted(Comparator.comparing((Map.Entry<String, Integer> e) -> e.getValue()).reversed())

                //Ergebnis ausgeben
                .forEach(System.out::println);
    }
}
 
Wenn man schonmal was von modernem Java gesehen hat…

Ist natürlich völlig unlegitim/illegitim(/unangemessen)/unangebracht/kontraproduktiv und deplatziert. Er wollte gerne eigene Klasse/Objekt (mit String und Zahl) haben. Nichts anderes als mein erster Beitrag macht dein Spaghetticode da. Aber schön, dass du Java 8 "kannst".

Und "du" hast Map für Buchstaben missbraucht. Das ist nicht modern - sondern langsam.
 
Zuletzt bearbeitet von einem Moderator:
Könntet Ihr mir bitte die Java 8 - 9 Lösung geben / zeigen? (Lambda/Funktional) Bin da etwas schwerfällig

Ist natürlich völlig unlegitim/illegitim(/unangemessen)/unangebracht/kontraproduktiv und deplatziert.[...]
Aber schön, dass du Java 8 "kannst".

Ok.

Und "du" hast Map für Buchstaben missbraucht. Das ist nicht modern - sondern langsam.

Ich glaube nicht, dass der Unterschied so gigantisch ist.
 
Generell war die Aufgabenstellung "Wörter" zu zählen, darum ist hier auch eine Map die richtige Wahl.
Ich "verbessere" die Java 8 Lösung von @klauskarambulut ein wenig, denn:
- Pattern kann schon einen Stream adhoc erzeugen
- Collector kann eingespart werden
- Spezielle Comparatoren gibt es für Entry-Klasse
- die 10 meistgezähltesten Worte sollten ausgegeben werden
- richtiges verwenden von terminal operations
Java:
Pattern.compile(",\\s*").splitAsStream(s).filter(str -> !str.isEmpty())
    .collect(Collectors.groupingBy(Function.identity(), Collectors.summingInt(str -> 1))).entrySet().stream()
    .sorted(Entry.<String, Integer>comparingByValue().reversed()).limit(10).forEachOrdered(System.out::println);
Wie man das jetzt handhabt, ob man hier Objekte verwendet oder Entry der Map, sei jetzt dem Anwendungsfall/Projekt überlassen.
 

Zurück
Oben