Texte zerstückeln, gruppieren und zählen

Hallo, womit fang’ ich an? Ich hab hier 'ne Nuss:

 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package javaapplication;

import java.io.*;
import java.net.*;
import java.util.*;
import org.*.*;
import org.*.*.*;

/**
 * @author CB
 */
public class WS {

    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
        ArrayList<Post> posts = loadPosts();
        printPosts(posts);
        HashMap<String, ArrayList<Post>> usersPosts = getMap1(posts);
        HashMap<String, HashMap<String, Integer>> usersWordsCounts = getMap2(usersPosts);
        HashMap<String, ArrayList<Word>> usersWords = getMap3(usersWordsCounts);
        printUsers(usersWords);
    }

    private static HashMap<String, ArrayList<Post>> getMap1(ArrayList<Post> posts) {
        HashMap<String, ArrayList<Post>> usersPosts = new HashMap<String, ArrayList<Post>>();
        for (Post p : posts) {
            if (!usersPosts.containsKey(p.name)) {
                usersPosts.put(p.name, new ArrayList<Post>());
            }
            usersPosts.get(p.name).add(p);
        }
        return usersPosts;
    }

    private static HashMap<String, HashMap<String, Integer>> getMap2(ArrayList<Post> posts) {
        
        HashMap<String  ,    HashMap<String, Word> > userWordSyno = new HashMap<String, HashMap<String, Word>>();
        
        for (Post p : posts) {
            if (!userWordSyno.containsKey(p.name)) {
                userWordSyno.put(p.name, new HashMap<String, Word>());
            }
            String[] sa = p.text.split("[^\\wÄäÖöÜüß]+");
            for (String s : sa) {
                if (s.isEmpty()) {
                    continue;
                }
                s = s.toLowerCase();
                if (wordsCounts.containsKey(s)) {
                    wordsCounts.put(s, wordsCounts.get(s) + 1);
                } else {
                    wordsCounts.put(s, 1);
                }
            }
        }
        
        
        HashMap<String, HashMap<String, Integer>> usersWordsCounts = new HashMap<String, HashMap<String, Integer>>();
        for (Post p : posts) {
            if (!usersWordsCounts.containsKey(p.name)) {
                usersWordsCounts.put(p.name, new HashMap<String, Integer>());
            }
            HashMap<String, Integer> wordsCounts = usersWordsCounts.get(p.name);
            String[] sa = p.text.split("[^\\wÄäÖöÜüß]+");
            for (String s : sa) {
                if (s.isEmpty()) {
                    continue;
                }
                s = s.toLowerCase();
                if (wordsCounts.containsKey(s)) {
                    wordsCounts.put(s, wordsCounts.get(s) + 1);
                } else {
                    wordsCounts.put(s, 1);
                }
            }
        }
        return usersWordsCounts;
        /* HashMap<String, HashMap<String, Integer>> usersWordsCounts = new HashMap<String, HashMap<String, Integer>>();
         for (String user : usersPosts.keySet()) {
         HashMap<String, Integer> wordsCounts = new HashMap<String, Integer>();
         for (Post p : usersPosts.get(user)) {
         String[] sa = p.text.split("[^\\wÄäÖöÜüß]+");
         for (String s : sa) {
         if (s.isEmpty()) {
         continue;
         }
         s = s.toLowerCase();
         if (wordsCounts.containsKey(s)) {
         wordsCounts.put(s, wordsCounts.get(s) + 1);
         } else {
         wordsCounts.put(s, 1);
         }
         }
         }
         usersWordsCounts.put(user, wordsCounts);
         }
         return usersWordsCounts; */
    }

    private static HashMap<String, ArrayList<Word>> getMap3(HashMap<String, HashMap<String, Integer>> usersWordsCounts) {
        HashMap<String, ArrayList<Word>> usersWords = new HashMap<String, ArrayList<Word>>();
        for (Map.Entry<String, HashMap<String, Integer>> e : usersWordsCounts.entrySet()) { // Users
            
            
            
             HashMap<Word, HashSet<Word>> tree   =    new  TreeMap<Word, ArrayList<Word>> ();
            for (Map.Entry<String, Integer> e2 : e.getValue().entrySet()) { // Wörter
                Word w = new Word();
                w.setUser(e.getKey());
                w.setWord(e2.getKey());
                w.setCount(e2.getValue());
                if (tree.containsKey(w)) {
                    tree.get(w).add(w);
                }
                if (tree.contains(w)) {
                    tree.floor(w).setCount(tree.floor(w).getCount() + e2.getValue());
                } else {
                    tree.add(w);
                }
            }

            ArrayList<Word> words = new ArrayList<Word>(tree);
            words.sort(new Comparator<Word>() {
                @Override
                public int compare(Word o1, Word o2) {
                    return Integer.compare(o2.getCount(), o1.getCount());
                }
            });
            usersWords.put(e.getKey(), words);
        }
        return usersWords;
    }

    private static ArrayList<Post> loadPosts() throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("woen_uns.txt"));
        ArrayList<Post> posts = (ArrayList<Post>) ois.readObject();
        ois.close();
        return posts;
    }

    private static void printPosts(ArrayList<Post> posts) {
        for (Post p : posts) {
            System.out.println(p);
            System.out.println("");
        }
    }

    private static void printUser(ArrayList<Word> words) {
        for (Word w : words) {
            System.out.printf("%-20s %-20s %04d%n", w.user, w.word, w.count);
        }
        System.out.println("");
    }

    private static void printUsers(HashMap<String, ArrayList<Word>> usersWords) {
        for (Map.Entry<String, ArrayList<Word>> e : usersWords.entrySet()) {
            printUser(e.getValue());
        }
    }

    private static String readUrl(String string) throws IOException {
        StringBuilder sb = new StringBuilder();
        // weiter ist geheim
        return sb.toString();
    }

    private static void savePosts(ArrayList<Post> posts) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("woen_uns.txt"));
        oos.writeObject(posts);
        oos.close();

        posts = sortPosts(posts);

        oos = new ObjectOutputStream(new FileOutputStream("woen_sor.txt"));
        oos.writeObject(posts);
        oos.close();
    }

    private static ArrayList<Post> scanBis(int bis) throws InterruptedException, IOException {
        ArrayList<Post> alp = new ArrayList<Post>();
        // weiter ist geheim
        return alp;
    }

    private static ArrayList<Post> sortPosts(ArrayList<Post> posts) {
        ArrayList<Post> posts2 = new ArrayList<Post>(posts);
        Collections.sort(posts2);
        return posts2;
    }
}

class Post implements Comparable<Post>, Serializable {

    String uhrz;
    String name;
    String text;

    @Override
    public int compareTo(Post o) {
        return name.compareTo(o.name);
    }

    @Override
    public String toString() {
        return "Post{" + "uhrz=" + uhrz + ", name=" + name + ", text=" + text + '}';
    }
}

/* class Word implements Comparable<Word>, Serializable {

    
    int count;
    HashSet<String> syno;

    public Word(String s) {
        count = 1;
        syno = new HashSet<String>();
        syno.add(s);
    }
    
    
    
    public void add(String s) {
        syno.add(s);
    }
    
    public void inc() {
        count++;
    }

    @Override
    public int compareTo(Word o) {
      return   Integer.compare(o.count, count);
    }

} */

class Word implements Comparable<Word>, Serializable {

    String user;
    String word;
    int count;

    @Override
    public int compareTo(Word o) {
        return Integer.compare(o.count, count);
    }

    @Override
    public String toString() {
        return "Word{" + "user=" + user + ", word=" + word + ", count=" + count + '}';
    }
}```

Es läuft nicht so ganz, wie ich mir das gedacht hab.

Es gibt auf Top-level zwei Schritte,

eine Liste mit allen Posts erstellen,
für jeden User wird jedes Wort gezählt und das wird in eine Map gelegt,
(es wird sortiert).

Jetzt kommen wir näher zum Prob (welche Datenstruktur), in

`HashMap<String, HashMap<String, Integer>>`

wird User, Wort/Wörter und Anzahl abgelegt.

Allerdings hab ich jetzt das Prob, dass HashM. quasi nur genau übereinstimmende Zeichenketten/-Sequenzen nimmt, kein etwa, ungefähr, Gruppierungen usw. Außerdem quasi nur das zuletzt eingefügte 'Vorkommen'.

Ich möchte aber... quasi für ein Begriff einen Oberbegriff und mehrere Unterbegriffe, sowie Summierung aller Begriffe 'Vorkommen' in einer Kategorie. Das Prob ist mit der Datenstruktur.

Ist das schlüssig?

Edit: `private` (noch) nicht vorgeschrieben, Bezeichner könnten noch anders.

<lästermodus>Eigentlich würde ich ja auf The Stanford NLP (Natural Language Processing) Group verweisen, aber wenn du nach der ganzen Zeit, die du dich jetzt schon (indirekt?) mit java beschäftigst, noch nicht weißt, dass dort meistens Map statt HashMap stehen solle, könnte das schwierig werden</lästermodus>
Geht es um eine allgemeine String-Ähnlichkeit?

[QUOTE=Marco13]<lästermodus>Eigentlich würde ich ja auf The Stanford NLP (Natural Language Processing) Group verweisen, aber wenn du nach der ganzen Zeit, die du dich jetzt schon (indirekt?) mit java beschäftigst, noch nicht weißt, dass dort meistens Map statt HashMap stehen solle, könnte das schwierig werden</lästermodus>
Geht es um eine allgemeine String-Ähnlichkeit?[/QUOTE]
Gegen das Interface programmieren, das würde ich erst zum Schluss machen. scrum, Bottom-up

Ich hab mir gedacht, zwei Strings sind gleich, wenn sie bis auf das letzte Zeichen gleich sind, oder komplett gleich sind.^^ Das mag die HashMap aber nicht, bzw.,

Map<String, Map<String, List>>

User, Wort, Synonyme, Anzahl <==> irgendwie irrsinnig, mMn.

Und in einer Liste suchen bedeutet n-Performance.

Ich hab Probleme mit Set und HashSet, wirklich schwerwiegende Probleme. Dachte mir, du machst sowas:


    @Override
    public int hashCode() {
        int hash = 7;
        hash = 31 * hash + (this.word != null ? this.word.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Word other = (Word) obj;
        if ((this.word == null) ? (other.word != null) : !this.word.equals(other.word)) {
            return false;
        }
        return true;
    }

    Post post;
    String word;
    HashSet<String> syno = new HashSet<String>();
    int count = 1;

    public Word(Post post, String word1, String word2) {
        this.post = post;
        this.word = word1;
        syno.add(word2);
    }

    public void add(String string) {
        syno.add(string);
        count++;
    }

    @Override
    public int compareTo(Word o) {
        int i1 = post.name.compareTo(o.post.name);
        int i2 = Integer.compare(o.count, count);
        if (i1 != 0) {
            return i1;
        }
        return i2;
    }

    @Override
    public String toString() {
        return "Word{" + "post=" + post + ", word=" + word + ", syno=" + syno + ", count=" + count + '}';
    }

}```

Funktioniert nicht, daaa, 1. ich kann in das Set anhand von word1 einfügen, 2. ich kann prüfen, ob word1 im Set enthalten ist, 3. ich kann NICHT (kostensparend) word1/Word aus einem Set wieder herausholen, das müüüsste ich aber machen, um ein Synonym hinzuzufügen.

Ich bin schon ganz traurig. :(

*** Edit ***

Hat, funktioniert, Ergebnis meiner Zählung:

[SPOILER]```CyborgBeta           0032 [ich]
CyborgBeta           0020 [auch]
CyborgBeta           0019 [das]
CyborgBeta           0016 [nicht]
CyborgBeta           0015 [man]
CyborgBeta           0012 [ein]
CyborgBeta           0012 [die]
CyborgBeta           0012 [ist]
CyborgBeta           0012 [wenn]
CyborgBeta           0011 [es]
CyborgBeta           0011 [und]
CyborgBeta           0010 [der]
CyborgBeta           0010 [von]
CyborgBeta           0010 [oder]
CyborgBeta           0009 [du]
CyborgBeta           0009 [bin]
CyborgBeta           0009 [mit]
CyborgBeta           0009 [werden]
CyborgBeta           0008 [aber]
CyborgBeta           0008 [so]
CyborgBeta           0008 [sind]
CyborgBeta           0008 [wie]
CyborgBeta           0007 [nichts, nichtsdestotrotz]
CyborgBeta           0007 [zitat]
CyborgBeta           0007 [kann]
CyborgBeta           0007 [dann]
CyborgBeta           0007 [nur]
CyborgBeta           0007 [einen]
CyborgBeta           0007 [anderes, andere, anderen]
CyborgBeta           0006 [weil]
CyborgBeta           0006 [sie]
CyborgBeta           0006 [für]
CyborgBeta           0006 [edit]
CyborgBeta           0006 [hat]
CyborgBeta           0006 [habe]
CyborgBeta           0006 [was]
CyborgBeta           0005 [gesagt]
CyborgBeta           0005 [mehr]
CyborgBeta           0005 [in]
CyborgBeta           0005 [mal]
CyborgBeta           0005 [doch]
CyborgBeta           0005 [sollte]
CyborgBeta           0005 [zu]
CyborgBeta           0005 [dass]
CyborgBeta           0005 [nihilistisch, nihilisten, nihilist]
CyborgBeta           0004 [1]
CyborgBeta           0004 [stunden]
CyborgBeta           0004 [gibt]
CyborgBeta           0004 [ja]
CyborgBeta           0004 [wieder]
CyborgBeta           0004 [ihr]
CyborgBeta           0004 [schlafe, schlaf]
CyborgBeta           0003 [den]
CyborgBeta           0003 [dem]
CyborgBeta           0003 [einfach]
CyborgBeta           0003 [glauben, glaube]
CyborgBeta           0003 **
CyborgBeta           0003 [schreibt, schreiben]
CyborgBeta           0003 [damit]
CyborgBeta           0003 [im]
CyborgBeta           0003 [euch]
CyborgBeta           0003 [eine]
CyborgBeta           0003 [adjektiven, adjektivgruppen, adjektive]
CyborgBeta           0003 [noch]
CyborgBeta           0003 [denn]
CyborgBeta           0003 [keine]
CyborgBeta           0003 [rue]
CyborgBeta           0003 [um]
CyborgBeta           0003 [mla]
CyborgBeta           0003 [auf]
CyborgBeta           0003 [aus]
CyborgBeta           0003 [sein]
CyborgBeta           0003 [alle]
CyborgBeta           0003 [gewissen]
CyborgBeta           0003 [mich]
CyborgBeta           0003 [weniger, wenigen]
CyborgBeta           0003 [bild]
CyborgBeta           0002 [reiche]
CyborgBeta           0002 [beigebracht]
CyborgBeta           0002 [dort]
CyborgBeta           0002 [an]
CyborgBeta           0002 [verneinen]
CyborgBeta           0002 [0]
CyborgBeta           0002 [angst]
CyborgBeta           0002 [5]
CyborgBeta           0002 [opfer]
CyborgBeta           0002 [wacker]
CyborgBeta           0002 [dazu]
CyborgBeta           0002 [sei]
CyborgBeta           0002 [diskussion]
CyborgBeta           0002 [h]
CyborgBeta           0002 [s]
CyborgBeta           0002 [z]
CyborgBeta           0002 [mein]
CyborgBeta           0002 [runter]
CyborgBeta           0002 [eh]
CyborgBeta           0002 [gehen]
CyborgBeta           0002 [gesellschaft]
CyborgBeta           0002 [steht]
CyborgBeta           0002 [eher]
CyborgBeta           0002 [denen]
CyborgBeta           0002 [bist]
CyborgBeta           0002 [vor]
CyborgBeta           0002 [wünsche]
CyborgBeta           0002 [neues]
CyborgBeta           0002 [sich]
CyborgBeta           0002 [haben]
CyborgBeta           0002 [deshalb]
CyborgBeta           0002 [hast]
CyborgBeta           0002 [essen]
CyborgBeta           0002 [hier]
CyborgBeta           0002 [kollektive]
CyborgBeta           0002 [schon]
CyborgBeta           0002 [guten]
CyborgBeta           0002 [jetzt]
CyborgBeta           0002 [seitengeländer, seiten]
CyborgBeta           0002 [bereit]
CyborgBeta           0002 [als]
CyborgBeta           0002 [sport]
CyborgBeta           0002 [formuliert]
CyborgBeta           0002 [nie]
CyborgBeta           0002 [jüngere]
CyborgBeta           0002 [morgen]
CyborgBeta           0002 [naja]
CyborgBeta           0002 [bleibt]
CyborgBeta           0002 [irgendwo, irgendwer]
CyborgBeta           0002 [etwas]
CyborgBeta           0002 [10]
CyborgBeta           0002 [vorbild, vorbilder]
CyborgBeta           0002 [wirklich]
CyborgBeta           0002 [brauche, brauchen]
CyborgBeta           0002 [selbstverständlich, selbst]
CyborgBeta           0002 [mir]
CyborgBeta           0002 [wichtigste, wichtige]
CyborgBeta           0002 [fragen]
CyborgBeta           0002 [wenig]
CyborgBeta           0002 [5h]
CyborgBeta           0002 [gar]
CyborgBeta           0002 [vereinfacht]
CyborgBeta           0002 [jeder]
CyborgBeta           0002 [gemeint]
CyborgBeta           0002 [dabei]
CyborgBeta           0002 [diese]
CyborgBeta           0002 [mindestlohn]
CyborgBeta           0002 [alles]
CyborgBeta           0002 [gleichrangigen, gleich]
CyborgBeta           0002 [eigentlich]
CyborgBeta           0002 [durch]
CyborgBeta           0002 [arbeit, arbeite]
CyborgBeta           0002 [halten]
CyborgBeta           0002 [leute]
CyborgBeta           0002 [sondern]
CyborgBeta           0002 [einem]
CyborgBeta           0002 [immer]
CyborgBeta           0002 [kein]
CyborgBeta           0002 [eigenen, eigene]
CyborgBeta           0002 [also]
CyborgBeta           0002 [trollende, trolle]
CyborgBeta           0001 [ausgekommen]
CyborgBeta           0001 [selber]


CyborgBeta           32                   [ich]
CyborgBeta           20                   [auch]
CyborgBeta           19                   [das]
CyborgBeta           16                   [nicht]
CyborgBeta           15                   [man]
CyborgBeta           12                   [ein]
CyborgBeta           12                   [die]
CyborgBeta           12                   [ist]
CyborgBeta           12                   [wenn]
CyborgBeta           11                   [es]
CyborgBeta           11                   [und]
CyborgBeta           10                   [der]
CyborgBeta           10                   [von]
CyborgBeta           10                   [oder]
CyborgBeta           9                    [du]
CyborgBeta           9                    [bin]
CyborgBeta           9                    [mit]
CyborgBeta           9                    [werden]
CyborgBeta           8                    [aber]
CyborgBeta           8                    [so]
CyborgBeta           8                    [sind]
CyborgBeta           8                    [wie]
CyborgBeta           7                    [nichts, nichtsdestotrotz]
CyborgBeta           7                    [zitat]
CyborgBeta           7                    [kann]
CyborgBeta           7                    [dann]
CyborgBeta           7                    [nur]
CyborgBeta           7                    [einen]
CyborgBeta           7                    [anderes, andere, anderen]
CyborgBeta           6                    [weil]
CyborgBeta           6                    [sie]
CyborgBeta           6                    [für]
CyborgBeta           6                    [edit]
CyborgBeta           6                    [hat]
CyborgBeta           6                    [habe]
CyborgBeta           6                    [was]
CyborgBeta           5                    [gesagt]
CyborgBeta           5                    [mehr]
CyborgBeta           5                    [in]
CyborgBeta           5                    [mal]
CyborgBeta           5                    [doch]
CyborgBeta           5                    [sollte]
CyborgBeta           5                    [zu]
CyborgBeta           5                    [dass]
CyborgBeta           5                    [nihilistisch, nihilisten, nihilist]
CyborgBeta           4                    [1]
CyborgBeta           4                    [stunden]
CyborgBeta           4                    [gibt]
CyborgBeta           4                    [ja]
CyborgBeta           4                    [wieder]
CyborgBeta           4                    [ihr]
CyborgBeta           4                    [schlafe, schlaf]
CyborgBeta           3                    [den]
CyborgBeta           3                    [dem]
CyborgBeta           3                    [einfach]
CyborgBeta           3                    [glauben, glaube]
CyborgBeta           3                    **
CyborgBeta           3                    [schreibt, schreiben]
CyborgBeta           3                    [damit]
CyborgBeta           3                    [im]
CyborgBeta           3                    [euch]
CyborgBeta           3                    [eine]
CyborgBeta           3                    [adjektiven, adjektivgruppen, adjektive]
CyborgBeta           3                    [noch]
CyborgBeta           3                    [denn]
CyborgBeta           3                    [keine]
CyborgBeta           3                    [rue]
CyborgBeta           3                    [um]
CyborgBeta           3                    [mla]
CyborgBeta           3                    [auf]
CyborgBeta           3                    [aus]
CyborgBeta           3                    [sein]
CyborgBeta           3                    [alle]
CyborgBeta           3                    [gewissen]
CyborgBeta           3                    [mich]
CyborgBeta           3                    [weniger, wenigen]
CyborgBeta           3                    [bild]
CyborgBeta           2                    [reiche]
CyborgBeta           2                    [beigebracht]
CyborgBeta           2                    [dort]
CyborgBeta           2                    [an]
CyborgBeta           2                    [verneinen]
CyborgBeta           2                    [0]
CyborgBeta           2                    [angst]
CyborgBeta           2                    [5]
CyborgBeta           2                    [opfer]
CyborgBeta           2                    [wacker]
CyborgBeta           2                    [dazu]
CyborgBeta           2                    [sei]
CyborgBeta           2                    [diskussion]
CyborgBeta           2                    [h]
CyborgBeta           2                    [s]
CyborgBeta           2                    [z]
CyborgBeta           2                    [mein]
CyborgBeta           2                    [runter]
CyborgBeta           2                    [eh]
CyborgBeta           2                    [gehen]
CyborgBeta           2                    [gesellschaft]
CyborgBeta           2                    [steht]
CyborgBeta           2                    [eher]
CyborgBeta           2                    [denen]
CyborgBeta           2                    [bist]
CyborgBeta           2                    [vor]
CyborgBeta           2                    [wünsche]
CyborgBeta           2                    [neues]
CyborgBeta           2                    [sich]
CyborgBeta           2                    [haben]
CyborgBeta           2                    [deshalb]
CyborgBeta           2                    [hast]
CyborgBeta           2                    [essen]
CyborgBeta           2                    [hier]
CyborgBeta           2                    [kollektive]
CyborgBeta           2                    [schon]
CyborgBeta           2                    [guten]
CyborgBeta           2                    [jetzt]
CyborgBeta           2                    [seitengeländer, seiten]
CyborgBeta           2                    [bereit]
CyborgBeta           2                    [als]
CyborgBeta           2                    [sport]
CyborgBeta           2                    [formuliert]
CyborgBeta           2                    [nie]
CyborgBeta           2                    [jüngere]
CyborgBeta           2                    [morgen]
CyborgBeta           2                    [naja]
CyborgBeta           2                    [bleibt]
CyborgBeta           2                    [irgendwo, irgendwer]
CyborgBeta           2                    [etwas]
CyborgBeta           2                    [10]
CyborgBeta           2                    [vorbild, vorbilder]
CyborgBeta           2                    [wirklich]
CyborgBeta           2                    [brauche, brauchen]
CyborgBeta           2                    [selbstverständlich, selbst]
CyborgBeta           2                    [mir]
CyborgBeta           2                    [wichtigste, wichtige]
CyborgBeta           2                    [fragen]
CyborgBeta           2                    [wenig]
CyborgBeta           2                    [5h]
CyborgBeta           2                    [gar]
CyborgBeta           2                    [vereinfacht]
CyborgBeta           2                    [jeder]
CyborgBeta           2                    [gemeint]
CyborgBeta           2                    [dabei]
CyborgBeta           2                    [diese]
CyborgBeta           2                    [mindestlohn]
CyborgBeta           2                    [alles]
CyborgBeta           2                    [gleichrangigen, gleich]
CyborgBeta           2                    [eigentlich]
CyborgBeta           2                    [durch]
CyborgBeta           2                    [arbeit, arbeite]
CyborgBeta           2                    [halten]
CyborgBeta           2                    [leute]
CyborgBeta           2                    [sondern]
CyborgBeta           2                    [einem]
CyborgBeta           2                    [immer]
CyborgBeta           2                    [kein]
CyborgBeta           2                    [eigenen, eigene]
CyborgBeta           2                    [also]
CyborgBeta           2                    [trollende, trolle]
CyborgBeta           1                    [ausgekommen]```[/SPOILER]

Man darf den Schlüssel nicht zu komplex werden lassen... :S

Thema gelöst.

Kann ich so nicht stehen lassen (CB wirds egal sein, also kannt er es gerne ignorieren. Das richtet sich an andere, die hier vorbei kommen und fälschlicherweise dieser Aussage glauben würden):
Weder bottom-up noch Scrum (eine Sache die ohne multiple Persönlichkeit alleine auch gar nicht möglich ist) verbieten dir das Programmieren gegen Interfaces (von beginn an). Scrum ist eine Methode zur agilen Softwareentwicklung in Teams und sorgt für möglichst kleine Aufgaben die im Team verteilt werden können. Was somit dann auch Bottom-up als Konsequenz hat (Basiselemente werden vom Team entwickelt und später zusammengesetzt).

Wenn du nach gleichen Präfixen suchst, kannst du einen Trie verwenden, z.B. aus Apache Commons: PatriciaTrie (Apache Commons Collections 4.0 API)

Nebenbei bemerkt sollte man generell nicht mit geschachtelten Map-Konstruktionen und so herumwerkeln. Guava hat Multimaps, Table…

Statistiken durch, beliebtes Thema:
56 [arbeitender, arbeitsfahrt, arbeiteten, arbeitswoche, arbeitslose, arbeit, arbeitest, arbeitswegkosten, arbeitenden, arbeitszeiten, arbeitsamt, arbeitslust, arbeitskollegen, arbeitsweise, arbeiter, arbeitszeit, arbeitslosenzahlen, arbeitet, arbeiten, arbeitstag, arbeite]
Oft genannt:
107 [michimitsu]
Synonyme von mir:
CyborgBeta 344 [cyborgbeta, cyborggamma, cyborgb, cyborgs, cyborgalpha, cyborg]
Kaffee:
72 [kaffeemaschinenentkalkungsfachkraft, kaffeetasse, kaffeemaschine, kaffee, kaffeeentzug, kaffeeabhängigkeiten, kaffeeproblem, kaffeebohnen, kaffeekonsum, kaffeemaschinenreinigungsfachkraft, kaffeetrinker, kaffeekanne, kaffeeduft]
Größe (unkomprimiert):
~ 3,5MB

Bin ich cool, also, da wäre noch was möglich.

Ja Präfixe, Trie whrs. Tree, Ja Tree:

        HashMap<String, HashMap<String, ArrayList<String>>> userWordSyno = new HashMap<String, HashMap<String, ArrayList<String>>>();
        for (Post p : posts) {
            if (!userWordSyno.containsKey(p.name)) {
                userWordSyno.put(p.name, new HashMap<String, ArrayList<String>>());
            }
            HashMap<String, ArrayList<String>> m1 = userWordSyno.get(p.name);
            String[] sa = p.text.split("[^\\wÄäÖöÜüß]+");
            for (String s : sa) {
                if (s.isEmpty()) {
                    continue;
                }
                s = s.toLowerCase();
                String key = s;
                if (s.length() > 5) {
                    key = s.substring(0, 5);
                }
                if (!m1.containsKey(key)) {
                    m1.put(key, new ArrayList<String>());
                }
                m1.get(key).add(s);
            }
        }
        return userWordSyno;
    }```

```    private static ArrayList<Word> getWordList(HashMap<String, HashMap<String, ArrayList<String>>> userWordSyno) {
        ArrayList<Word> wordList = new ArrayList<Word>();
        for (Map.Entry<String, HashMap<String, ArrayList<String>>> e1 : userWordSyno.entrySet()) {
            for (Map.Entry<String, ArrayList<String>> e2 : e1.getValue().entrySet()) {
                Word w = new Word(e1.getKey(), new TreeSet<String>(e2.getValue()), e2.getValue().size());
                wordList.add(w);
            }
        }
        Collections.sort(wordList);
        return wordList;
    }```

```    @Override
    public int compareTo(Word o) {
        int i1 = name.compareTo(o.name);
        int i2 = Integer.compare(o.count, count);
        int i3 = tree.first().compareTo(o.tree.first());
        if (i1 != 0) {
            return i1;
        }
        if (i2 != 0) {
            return i2;
        }
        return i3;
    }```

Space: Für zwei Wörter in unterschiedlichen Trees gilt, dass sie unterschiedlich sein müssen.

Problem was ich hatte, ich brauche einen
`int count;`
für "doppelte Wörter",
deshalb Umweg über ArrayList / Liste.

`s.substring(5 Zeichen lang);` ist natürlich nicht so toll, aber alles andere viel zu umständlich.

Speicherverbrauch "Rohdaten" (Liste mit Posts): ~ 3,5 MB
Speicherverbrauch (Map +) Map + Liste: ~ 5,8 MB
Speicherverbrauch Liste + Tree: ~ 3,2 MB

Alles läuft in n durch, neues TreeSet aufbauen: unter n*n.

Besser geht's doch gar nicht (es geht tatsächlich nicht besser).

Nein, ein Trie ist etwas anderes (besser gesagt, ein sehr spezieller) Tree. Wieso verlinke ich zu einer Implementierung, wenn du das sowieso ignorierst?

Und nochmal: Wenn du etwas wie HashMap<String, HashMap<String, ArrayList<String>>> verwendest, machst du definitiv etwas falsch.

Hat sich ja schon aufgeklärt, kann sein, das dir die Signatur nicht gefällt,…

Ich brauchte (Vergangenheitsform) einen Tree, der sich zusätzlich merkt, wie oft versucht wurde, einzufügen, und wie oft tatsächlich. Das Thema könnte als gelöst betrachtet werden.

Ich werf mal noch ne fachliche Frage rein, ohne Absicht den Thread Hijacken zu wollen:
Warum sind in Java verschachtelte Collections “schlecht” und welche Alternativen gibt es?

[QUOTE=Sen-Mithrarin]Ich werf mal noch ne fachliche Frage rein, ohne Absicht den Thread Hijacken zu wollen:
Warum sind in Java verschachtelte Collections “schlecht” und welche Alternativen gibt es?[/QUOTE]

Ist nicht Offtopic, alternative sind “geschachtelte” Klassen, also Klassen mit Referenzen auf Klassen. Aber ich bin mir sicher, das erzeugt mehr Overhead und ist auch “ein wenig” langsamer.

  int ichZaehleEtwas;
  Lists<String> eineWichtigeListe; // ich kann auch ausgetauscht werden
}

class B {
  Map<String, A> eineWichtigeMap;
}

class C {
  Map<String, B> nochEineSehrWichtigeMap;
}```

Es ist einfach ein Erfahrungswert, dass verschachtelte Collections fast nie das ausdrücken, was man wirklich haben will.

Nehmen wir z.B. Map<String, Set<String>>. Es mag hin und wieder Fälle geben, wo ich wirklich eine Map von Strings auf String-Sets brauche - in dem Sinne, dass die Sets selbst (und nicht die darin gespeicherten Strings) die Werte sind, die mich wirklich interessieren. Dann kommt es aber in der Regel dazu, dass das Set recht bald in eine eigene Wert-Klasse mutiert, die zusätzliche Funktionalität bietet, man also am Ende bei etwas “ungeschachteltem” wie Map<String, Wortliste> oder so ankommt. In den allermeisten Fällen will ich aber eine Datenstruktur, die es erlaubt, mehrere Werte unter einem Schlüssel abzulegen, also z.B. eine Multimap<String, String> in Guava.

Die Unterschiede bei der Benutzung sind gravierend. Wenn ich einen String-Wert einfügen möchte, muss ich im ersten Fall erst einmal sicherstellen, dass unter dem Schlüssel überhaupt ein Set gespeichert ist. Wenn ich einen String-Wert lösche, kann ein leeres Set übrigbleiben, das dann ebenfalls gelöscht werden muss (jedenfall wenn ich später die korrekte Antwort auf “gibt es Werte zu diesem Schlüssel” bekommen will). Oder wenn ich alle String-Werte haben will, muss ich erst einmal über alle Sets iterieren. Die Sets behindern mich ständig, weil sie nur eine Krücke sind, um meine eigentlichen Absichten in ein Map-Korsett pressen zu können.

All das ist bei einer Multimap überflüssig, sie funktioniert einfach so, wie man es von einer Art Map, die aber mehrere Werte pro Schlüssel erlaubt, erwarten würde. Operationen wie Einfügen, Löschen, Suchen u.s.w. können dort wieder in einem Schritt ausgeführt werden.

Die üblichsten “Ersatzklassen” sind Multiset (a.k.a. Bag), Multimap, Bi(directional)Map und Table (sozusagen eine 2D-Map mit einem “Spalten”- und einem “Zeilen”-Schlüssel)

Schön erklärt, aber ich muss nicht das letzte bisschen Performance rausholen, wenn es um 1,5mb mehr oder weniger Speicherplatzverhalten geht - es sei denn, es geht um einen Mikrocontroller oÄ. aber dann wird man eh keine echte Klasse genießen dürfen.

Wo hast du denn was von Performance gelesen? Mit den guava collections (um eine Implementierung stellvertretend für ein Konzept zu nehmen) ist die Verwendung der Collections wieder intuitiv und lesbar, weil man nicht ständig Verwaltungsarbeit erledigen muss.
Ob das intern alles effizienter implementiert ist, ist erst einmal nebensächlich.

[QUOTE=cmrudolph]Wo hast du denn was von Performance gelesen? Mit den guava collections (um eine Implementierung stellvertretend für ein Konzept zu nehmen) ist die Verwendung der Collections wieder intuitiv und lesbar, weil man nicht ständig Verwaltungsarbeit erledigen muss.
Ob das intern alles effizienter implementiert ist, ist erst einmal nebensächlich.[/QUOTE]
Nichts gegen einzuwenden.

@ Sen : Nächster Kritikpunkt, den du vielleicht meintest, könnte sein, ArrayList enthält doppelte Elems - aber nur Referenzen. :o)

@CB
Nö, war halt nur die Frage warum geschachtelte Collections nicht gut sind, und die hat Landei recht gut erklärt: sie drücken nicht das aus was das Konstrukt vermuten lässt. Das Beispiel mit Map<String, Set> ist gut gewählt und einfach verständlich, vor allem mit dem Hinweis: “Gibt es zu Schlüssel X einen Wert?” dann ist ja in dem Fall interessant das es halt gar kein mapping gibt, und nicht auf ein leer Set das man dann erst auf “Bist du leer?” prüfen muss.

[QUOTE=Sen-Mithrarin]@CB
Nö, war halt nur die Frage warum geschachtelte Collections nicht gut sind, und die hat Landei recht gut erklärt: sie drücken nicht das aus was das Konstrukt vermuten lässt. Das Beispiel mit Map<String, Set> ist gut gewählt und einfach verständlich, vor allem mit dem Hinweis: “Gibt es zu Schlüssel X einen Wert?” dann ist ja in dem Fall interessant das es halt gar kein mapping gibt, und nicht auf ein leer Set das man dann erst auf “Bist du leer?” prüfen muss.[/QUOTE]

Ja, das ist der Nachteil, den hätte man aber auch mit jedem anderen komplexen Typ, es muss immer isEmpty geprüft werden, auch bei eigener Klasse, drei Zeilen mehr oder weniger, als Work-around schreibt man sich dafür eine Methode, so kann man es nicht vergessen.

Klar, ist das mit den Interfaces wichtig, aber solange man “das Konstrukt” nicht nach außen trägt, sehe ich darin für mich gar kein Problem, du etwa? Beef beendet?

[QUOTE=CyborgBeta]Ja, das ist der Nachteil, den hätte man aber auch mit jedem anderen komplexen Typ, es muss immer isEmpty geprüft werden, auch bei eigener Klasse, drei Zeilen mehr oder weniger, als Work-around schreibt man sich dafür eine Methode, so kann man es nicht vergessen.

Klar, ist das mit den Interfaces wichtig, aber solange man “das Konstrukt” nicht nach außen trägt, sehe ich darin für mich gar kein Problem, du etwa? Beef beendet?[/QUOTE]

Ähm bei meiner eigenen Klasse muss ich das nicht unbedingt, da diese das für mich erledigt,…