Collections Word-Frequenzen zählen

Landei

Top Contributor
Ich habe einmal darüber meditiert, wie man performant die Word-Frequenzen eines Textes ermittelt, wobei aber der aktuelle Stand jederzeit geordnet abrufbar sein soll (ansonsten ist das Problem trivial). Ich bin nur auf ein umständliches Hin und Her mit zwei Maps gekommen. Denke ich hier zu kompliziert?

Java:
public class WordCount {

    private final Map<String, Integer> wordFreq = new HashMap<String, Integer>();
    private final SortedMap<Integer, Set<String>> freqWord = new TreeMap<Integer, Set<String>>();

    public void add(String word) {
        int freq = 1;
        if (wordFreq.containsKey(word)) { //wir müssen den alten Eintrag löschen
            freq = wordFreq.get(word);
            Set<String> set = freqWord.get(freq);
            set.remove(word);
            if(set.isEmpty()) { //Einträge mit leeren Sets vermeiden
                freqWord.remove(freq);
            }
            freq++;
        }
        wordFreq.put(word, freq);
        Set<String> set = freqWord.get(freq);
        if (set == null) { //Eintrag mit neuem Set anlegen
            set = new TreeSet<String>();
            freqWord.put(freq, set);
        }
        set.add(word);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (Entry<Integer, Set<String>> entry : freqWord.entrySet()) {
            sb.append(entry.getKey()).append(":").append(entry.getValue()).append("\n");
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        WordCount wc = new WordCount();
        wc.add("a");
        wc.add("b");
        wc.add("a");
        wc.add("a");
        wc.add("c");
        System.out.println(wc);
        System.out.println();
        wc.add("d");
        wc.add("d");
        System.out.println(wc);
    }
}
 

bERt0r

Top Contributor
Du könntest das ganze gleich in einer SortedMap <String, Integer> speichern und der Map einen Comparator geben, der eben aufgrund der Values, nicht der Keys sortiert.
Ob das dann performanter ist als deine zwei Maps kann ich nicht sagen.
 
G

Gast2

Gast
Hm, so eine "geschummelte" Lösung suchst du nicht oder?

Java:
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class WordCount {
	private final Map<String, WordFrequency> wordFrequencies;

	private boolean isSorted = false;
	private List<WordFrequency> sortedWordFrequencies;

	public WordCount() {
		wordFrequencies = new HashMap<String, WordFrequency>();
	}

	public void add(String word) {
		if (!wordFrequencies.containsKey(word)) {
			wordFrequencies.put(word, new WordFrequency(word));
		} else {
			wordFrequencies.get(word).increaseFrequencyByOne();
		}

		isSorted = false;
	}

	@Override
	public String toString() {
		if (!isSorted) {
			sortWordFrequencies();
		}

		StringBuilder sb = new StringBuilder();
		for (WordFrequency wf : sortedWordFrequencies) {
			sb.append(wf.word).append(" : ").append(wf.frequency).append("\n");
		}
		return sb.toString();
	}

	private void sortWordFrequencies() {
		sortedWordFrequencies = new ArrayList<WordFrequency>(
				wordFrequencies.size());

		for (Entry<String, WordFrequency> entry : wordFrequencies.entrySet()) {
			sortedWordFrequencies.add(entry.getValue());
		}

		Collections.sort(sortedWordFrequencies);
		isSorted = true;
	}

	private static class WordFrequency implements Comparable<WordFrequency> {
		private final String word;
		private int frequency;

		public WordFrequency(String word) {
			this.word = word;
			this.frequency = 1;
		}

		public void increaseFrequencyByOne() {
			frequency++;
		}

		@Override
		public int compareTo(WordFrequency o) {
			return o.frequency - frequency;
		}
	}

	public static void main(String[] args) {
		WordCount wc = new WordCount();
		wc.add("a");
		wc.add("b");
		wc.add("a");
		wc.add("a");
		wc.add("c");
		System.out.println(wc);
		System.out.println();
		wc.add("d");
		wc.add("d");
		System.out.println(wc);
	}

}
 

Landei

Top Contributor
Du könntest das ganze gleich in einer SortedMap <String, Integer> speichern und der Map einen Comparator geben, der eben aufgrund der Values, nicht der Keys sortiert.
Ob das dann performanter ist als deine zwei Maps kann ich nicht sagen.

Das nützt aber nichts, wenn sich die Frequenz eines Wortes dauernd ändert.

@EikeB: In der Praxis könnte so ein "gemogeltes" Vorgehen durchaus sinnvoll sein, aber mir geht es eher um die theoretische Frage, wie man mein Vorgaben "datenstrukturtechnisch" umsetzen könnte.
 
G

Gast2

Gast
Wenn sich das Sortierkriterium laufend ändert seh ich so auf die schnelle keinen anderen Weg als die Datensätze jedesmal neu einzuordnen. Das könnte man z.b. mit ner SortedMap lösen, die das neu ordnen für einen erledigt.

EDIT:
Oder nen SortedSet, wär vielleicht ein wenig schlauer

EDIT2:
So vielleicht, auf Anhieb fällt mir da keine schlauere Datenstruktur ein.
Java:
public class WordCount2 {
	private final SortedSet<WordFrequency> wordFrequencies;
	
	public WordCount2() {
		wordFrequencies = new TreeSet<WordFrequency>();
	}
	
	public void add(String word) {
		WordFrequency wordFrequency = getAndRemoveWordFrequency(word);
		
		if (wordFrequency == null) {
			wordFrequency = new WordFrequency(word);
		} else {
			wordFrequency.increaseFrequencyByOne();
		}
		
		wordFrequencies.add(wordFrequency);
	}
	
	private WordFrequency getAndRemoveWordFrequency(String word) {
		Iterator<WordFrequency> iterator =  wordFrequencies.iterator();
		while (iterator.hasNext()) {
			WordFrequency wf = iterator.next();
			if (wf.getWord().equals(word)) {
				iterator.remove();
				return wf;
			}
		}
		
		return null;
	}
	
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		for (WordFrequency wf : wordFrequencies) {
			sb.append(wf.word).append(" : ").append(wf.frequency).append("\n");
		}
		return sb.toString();
	}
	
	private static class WordFrequency implements Comparable<WordFrequency> {
		private final String word;
		private int frequency;

		public WordFrequency(String word) {
			this.word = word;
			this.frequency = 1;
		}

		public void increaseFrequencyByOne() {
			frequency++;
		}

		public String getWord() {
			return word;
		}

		@Override
		public int compareTo(WordFrequency o) {
			if (o.frequency == frequency) {
				return o.word.compareTo(word);
			} else {
				return o.frequency - frequency;
			}
		}
	}
	
	public static void main(String[] args) {
		WordCount2 wc = new WordCount2();
		wc.add("a");
		wc.add("b");
		wc.add("a");
		wc.add("a");
		wc.add("c");
		System.out.println(wc);
		System.out.println();
		wc.add("d");
		wc.add("d");
		System.out.println(wc);
	}
}
 
Zuletzt bearbeitet von einem Moderator:

bERt0r

Top Contributor
Das nützt aber nichts, wenn sich die Frequenz eines Wortes dauernd ändert.

@EikeB: In der Praxis könnte so ein "gemogeltes" Vorgehen durchaus sinnvoll sein, aber mir geht es eher um die theoretische Frage, wie man mein Vorgaben "datenstrukturtechnisch" umsetzen könnte.

Genau das gleiche machst du doch auch, nur eben mit einer zweiten Collection, die man bei meinem Ansatz nicht braucht. Wenn sich der Wert erhöht, wird gegebenenfalls gelöscht (bin mir nicht sicher ob es mit einfachem überschreiben richtig sortiert wird) und neu eingefügt. Der Comparator sorgt dafür, dass die Wörter nach der Häufigkeit sortiert, richtig eingefügt werden.
 

Marco13

Top Contributor
Ich finde, das ist eigentlich schon eine sehr kompakte und elegante Lösung. Man könnte sich eine Klasse machen, die das wegkapselt und wie eine normale Map aussieht ... oder nimm einfach Scala! :joke: Nee im Ernst: bezieht sich die Frage auf die "Menge des Codes", oder auf das etwas unhandliche Einfügen, weil man die Sortierung nachträglich nicht mehr ändern kann? Um das zu vermeiden bräuchte man irgendeinen Heap, dem man sagen kann: "heap.sortValueChanged(element, newValue)", und der dann die Sortierung auf Basis des neuen Wertes wiederherstellt - aber wenn das effizient sein soll (und man diesen Anspruch an sich selbst hat ;)) sollte das ein Fibonacci-Heap sein. Den schüttelt man nicht einfach aus dem Ärmel...
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
B Per Java Word Dokument schreiben? Allgemeine Java-Themen 8
E Ersetzen eines Bildes in der Kopfzeile eines Word-Docx-Dokuments mit Apache POI XWPF Allgemeine Java-Themen 0
I Apache POI Bild in Word ersetzen Allgemeine Java-Themen 15
M Aus XML ein Word-Dokument(Template) füllen Allgemeine Java-Themen 8
I Text suchen und ersetzen im Word Dokument Allgemeine Java-Themen 3
RalleYTN float in WORD konvertieren Allgemeine Java-Themen 1
J Datentypen Absätze mit String im Word Dokument Allgemeine Java-Themen 3
J Input/Output Word Datei einlesen, verarbeiten und abspeichern Allgemeine Java-Themen 3
Thallius PDF oder Word als Template benutzen Allgemeine Java-Themen 1
I Apache POI Word Text einfügen Allgemeine Java-Themen 26
D Symbol in Word-Dokument einfügen Allgemeine Java-Themen 1
D OOXML-Schemas (Word / Fußzeile) Allgemeine Java-Themen 0
K Apache POI Word Tabelle Zellen verbinden Allgemeine Java-Themen 4
K Apache POI Word Tabelle Spaltenbreite festlegen Allgemeine Java-Themen 7
K Apache POI Word bestimmte Textstellen bearbeiten Allgemeine Java-Themen 1
T Word Java Absatz Allgemeine Java-Themen 4
R MS Word in PDF konvertieren Allgemeine Java-Themen 1
T Mit Apache Poi Daten aus einer Excel Tabelle kopieren und in Word einfügen Allgemeine Java-Themen 1
H Input/Output Microsoft Word aus JAVA Heraus Steuern. Allgemeine Java-Themen 3
M Word mit Parameterübergabe Allgemeine Java-Themen 2
M Syntax Highlighter für MS Word? Allgemeine Java-Themen 2
Beckenbauer Mehrere Paragraphe in eine Word Datei schreiben Allgemeine Java-Themen 4
S Formatierungen aus HTML-Dokument übernehmen und in Word docx schreiben Allgemeine Java-Themen 3
S Automatisierte generierung von "Word"-Dokumenten Allgemeine Java-Themen 5
K Word Dokument bearbeiten Allgemeine Java-Themen 2
Blacky_82 word-Vorlage in java öffnen Allgemeine Java-Themen 4
ARadauer Word Datein bearbeiten Allgemeine Java-Themen 3
MQue aus einem Applet auf Word zugreifen Allgemeine Java-Themen 3
M Speichern von Word als Event abfangen Allgemeine Java-Themen 7
F Plugin damit M$ Word Java syntax versteht? Allgemeine Java-Themen 12
K Bilder mit Java in MS Word einfügen Allgemeine Java-Themen 2
Z Word/PDF Generierung Allgemeine Java-Themen 5
S Java Code in Word Allgemeine Java-Themen 8
H Word Dateien erstellen Allgemeine Java-Themen 2
C Word Datei /Serienbrief erstellen Allgemeine Java-Themen 8
P word zu pdf konvertieren Allgemeine Java-Themen 5
H RTF zu Word-Dokument generieren Allgemeine Java-Themen 5
G Daten nach Word exportieren Allgemeine Java-Themen 2
G Word-Dokument in einem JFrame Allgemeine Java-Themen 2
D API für MS-Word Allgemeine Java-Themen 7
T Word, Excel u. Access API Allgemeine Java-Themen 2
R Datenübergabe: Java zu MS Word-Vorlage Allgemeine Java-Themen 6
A HTML, WORD, EXCEL API Allgemeine Java-Themen 4
P free lib: PDF Formulare - Word Formulare Allgemeine Java-Themen 7
J Word Vorlagen öffnen und mit Daten füttern Allgemeine Java-Themen 2
L Serienbrief in word mit übergabewerten? Allgemeine Java-Themen 9
D Word, Excel oder sonstige Dateien extern ausführen Allgemeine Java-Themen 9
S Word-Dokument in Textarea anzeigen Allgemeine Java-Themen 2
Fabiator Variablen Variablen Zählen Allgemeine Java-Themen 3
S Drools: Zählen wie oft ein Wert vorkommt Allgemeine Java-Themen 1
R Methoden Was fehlt mir bzw. muss ich bei der Methode countHarshabNumbers ändern damit ich die Harshad Zahlen im Intervall [51, 79] zählen kann? Allgemeine Java-Themen 19
A Binärer Suchbaum Knoten Zählen Allgemeine Java-Themen 4
L Menge der Buchstaben eines Textes zählen Allgemeine Java-Themen 3
J Rekursive Programmierung-Zählen von Ziffern Allgemeine Java-Themen 5
J Die Menge einer Zahl im Binärbaum zählen Allgemeine Java-Themen 7
N [stream-api] Parameter pro Typ zählen Allgemeine Java-Themen 1
B Counting Sort (Sortieren durch Zählen) Allgemeine Java-Themen 13
K Wörter in Strings zählen Allgemeine Java-Themen 7
D Fehlgeschlagene Logins zählen... Was ist sinnvoll? Allgemeine Java-Themen 2
R Zusammenhängende Werte in 2-dim. Array finden und zählen Allgemeine Java-Themen 3
C Kleinbuchstaben zählen Allgemeine Java-Themen 10
P Werte in Array zählen und Summe der einzelnen Teile ausgeben Allgemeine Java-Themen 10
M Ein bestimmtes Wort in einem Text zählen (String in String) Allgemeine Java-Themen 9
B substring zählen Allgemeine Java-Themen 7
C Mausklicks zählen (extern) Allgemeine Java-Themen 6
S Knoten zählen in einem Binärbaum Allgemeine Java-Themen 2
S erzeugte objekte zählen Allgemeine Java-Themen 3
H Zeitraum: Arbeitstage zählen Allgemeine Java-Themen 5
J String Wörter zählen Allgemeine Java-Themen 4
S Array: Anzahl Elemente mit best. Wert zählen Allgemeine Java-Themen 4
M Anwendung nur einmal starten / Zeichen in String zählen Allgemeine Java-Themen 7
G Dateien und Verzeichnisse in einem Verzeichnis zählen Allgemeine Java-Themen 9
2 Tage zwischen zwei Datumsdaten zählen Allgemeine Java-Themen 2
G Tage zwischen zwei Datumsdaten zählen Allgemeine Java-Themen 3
G arguemente einer Methode zählen? Allgemeine Java-Themen 19
X Strings aus einer ArrayList zählen Allgemeine Java-Themen 11
B Farben Zählen Allgemeine Java-Themen 17
S Methode zum Zählen von Buchstaben in Strings gesucht Allgemeine Java-Themen 11
I vergleich und zählen von Strings Allgemeine Java-Themen 7
C Objekte einer Klasse zählen Allgemeine Java-Themen 25
T Zeilen eines Projekts zählen lassen Allgemeine Java-Themen 14
M richtiges Ergebnis zählen und übergeben? Allgemeine Java-Themen 7
F Dateien in einem Ordner zählen Allgemeine Java-Themen 15
G ziffern zählen mit rekursiver methode Allgemeine Java-Themen 2
F Zählen wie oft Methode aufgerufen wurde Allgemeine Java-Themen 2
L Häufigkeit der Werte in Datei zählen! Heap Space beschränkt! Allgemeine Java-Themen 31
F Bestimmes zeichen im String zählen Allgemeine Java-Themen 34
G Dateien zählen im Verzeichnis Allgemeine Java-Themen 11
B Integer zählen bzw. speichern Allgemeine Java-Themen 3
S lines of code zählen Allgemeine Java-Themen 9
A Buchstaben zählen Allgemeine Java-Themen 5

Ähnliche Java Themen

Neue Themen


Oben