Häufigkeitsanalyse

Jasmin589

Mitglied
Hallo zusammen, ich möchte gerne eine Häufigkeitsanalyse selber schreiben. Als erstes muss man dafür ja die Buchstaben aus einer Eingabe zählen, dass hatte ich zuerst mit Arrays realisiert. Jetzt bin ich im Netz aber auf eine "bessere" Variante gestoßen
Code:
import java.util.HashMap;
import java.util.Set;

public class Main
{
   
    public static void main(String[] args) 
    {
    
    String input = "Das ist ein Test";
    HashMap<Character, Integer> charMap = new HashMap<Character, Integer>();
   
    for (int i = 0; i < input.length(); i++) {
        Character key = input.charAt(i);
        if (charMap.containsKey(key)) {
            charMap.put(key, charMap.get(key)+1);
        } else {
            charMap.put(key, 1);
        }
    }
   
    Set<Character> keySet =  charMap.keySet();
    for (Character character : keySet)
    {
        System.out.println(character + " = " + charMap.get(character));
    }
   
    }
}

Daraufhin hab ich mir was zu HashMaps durchgelesen, aber ich versteh noch nicht ganz was der Code jetzt genau macht. Kann mir da jemand Stück für Stück erklären was passiert?
 

Jasmin589

Mitglied
Nichts gegen dich, aber die Antwort bringt mir jetzt eher nix. Ich mein ich will es ja lernen und wenn es dafür einen eleganteren Weg gibt, den wohl viele so machen dann würde ich auch gerne wissen wie der funktioniert.
 
X

Xyz1

Gast
Damit ich auch was zu Frage beitrage: Die Map zählt die Häufigkeit der Buchstaben.

"eleganter Weg"/best practice: Hab ich dir doch schon gesagt, nimm Arrays....
 

Flown

Administrator
Mitarbeiter
Ahh, jetzt erst verstanden, du bist der Meinung, das sei guter Code,... ist es aber nicht, falsche Vorgehensweise und veraltet...
Äh was?

Du kannst nicht immer mit solchen Argumenten daherspaziert kommen und dann keine Begründung dafür liefern.

@Jasmin589 Der Code oben sieht schon mal nicht schlecht aus.
Mit neueren Java features lässt sich das auch noch ein wenig verkürzen:
Java:
String input = "Das ist ein Test";
Map<Character, Integer> frequencies = new HashMap<>();
for (int i = 0; i < input.length(); i++) {
  frequencies.merge(input.charAt(i), 1, Integer::sum);
}
frequencies.forEach((key, value) -> System.out.format("'%c' = %d%n", key, value));
Dein Code nochmal erklärt:
Java:
String input = "Das ist ein Test";
Map<Character, Integer> charMap = new HashMap<>();

for (int i = 0; i < input.length(); i++) {
  // char an der i-ten Stelle des Strings auslesen
  Character key = input.charAt(i);
  // Prüfe, ob char schon in der Map existiert
  if (charMap.containsKey(key)) {
    // Wenn ja, dann hol den Wert, erhöhe ihn um 1 und lege ihn wieder in
    // der Map ab
    charMap.put(key, charMap.get(key) + 1);
  } else {
    // Wenn nein, dann leg den char mit dem Wert 1 ab
    charMap.put(key, 1);
  }
}

//EntrySet gibt gleich Key-Value Paare zurück
for (Entry<Character, Integer> entry : charMap.entrySet()) {
  System.out.println(entry.getKey() + " = " + entry.getValue());
}
 

Jasmin589

Mitglied
Endlich eine gescheite Antwort danke schonmal Flown.

Kannst du noch erklären, wie deins zustande kam? Vorallem das mit dem frequencies sehe ich zum ersten mal.
 

Flown

Administrator
Mitarbeiter
Wie schon gesagt, die Map::merge Methode ist in Java 8 dazu gekommen und macht eigentlich im Hintergrund genau das gleiche wie dein if-else Konstrukt.
Sachen wie (key, value) -> ... oder Integer::sum sind Lambda-Ausdrücke und Methodenreferenzen und gehören in die fortgeschrittene Sparte.

Bleib doch mal bei deinem Beispiel und versuche zu verstehen, was da vor sich geht.
 

mariane

Mitglied
Die erste for-Schleife könnte man auch index-frei gestalten, der Rest bliebe unverändert
Java:
for (Character key:input.toCharArray()) {
    if (charMap.containsKey(key)) {
        charMap.put(key, charMap.get(key)+1);
        continue;
    }
    charMap.put(key, 1);
}
 

Meniskusschaden

Top Contributor
Mit getOrDefault()kann man auch noch auf die Bedingung verzichten:
Java:
        for (Character key:input.toCharArray()) {
            charMap.put(key, charMap.getOrDefault(key, 0)+1);
        }
 

mrBrown

Super-Moderator
Mitarbeiter
Oder mit merge:
Java:
        for (Character key:input.toCharArray()) {
            charMap.merge(key, 1, Integer::sum);
        }

Und die Variante mit Stream und groupingBy gibts natürlich auch noch...
 

JStein52

Top Contributor
Ein Lehrbeispiel dafür wie man eine einfache Frage stellt und Antworten erhält .......
die nichts mit der Frage zu tun haben. Gibt es eigentlich neben "wie stellt man Fragen richtig " auch ein "Wie beantwortet man Fragen richtig" ?
 

Neue Themen


Oben