2010-08-01 9 views
6

J'ai reçu une affectation de vocabulaire en anglais par mon professeur.Travailler avec d'énormes fichiers texte en Java

Choisissez un alphabet aléatoire, dire 'a' Ecrire un mot de l'alphabet, disons 'pomme' Prenez le dernier mot 'e' Ecrire un mot de e, dire éléphant Maintenant de 't' et ainsi de suite .. Aucune répétition autorisée

Faites une liste de 500 mots. Envoyez la liste à l'enseignant. :)

Donc, au lieu de le faire moi-même, je travaille sur un code Java qui fera mes devoirs pour moi. Le code semble être simple.

Le cœur de l'algorithme: Récupère un mot aléatoire d'un dictionnaire, ce qui satisfait aux exigences. seek() avec RandomAccessFile. Essayez de le mettre dans un ensemble avec la commande (peut-être LinkedHashSet)

Mais le problème est l'énorme taille du dictionnaire avec 300 000+ enteries. : | Les algorithmes aléatoires de force brute ne fonctionneront pas.

Quelle pourrait être la solution la meilleure, la plus rapide et la plus efficace?

**** MISE À JOUR: ** Maintenant que j'ai écrit le code et son fonctionnement. Comment puis-je le rendre efficace afin qu'il choisisse des mots communs? Tous les fichiers texte contenant une liste de mots communs autour de? **

+0

FYI: 1 lakh = 100000 – miku

+0

À peu près conscient de cela. Le fichier texte est de 4MB! –

+1

4Mo est plutôt petit, non? – miku

Répondre

4

Cherchez une structure de données vous permettant de conserver un dictionnaire compacté en mémoire, ou donnez simplement plus de mémoire à votre processus. Trois cent mille mots, ce n'est pas beaucoup.

+0

Et utilisez un conteneur de dictionnaire java (par exemple) hashmap pour mettre votre fichier dictionnaire bien sûr: p (je l'ai lu comme il cherche toujours à partir du fichier). – KillianDS

+0

Je cherche toujours à partir d'un fichier jusqu'à maintenant. : | –

+2

@Myth, ne pas - il suffit de le lire dans un HashMap et de travailler avec ça. –

0

Je pense qu'une façon de faire cela pourrait être d'utiliser un TreeSet où vous mettez tout le dictionnaire puis utilisez la méthode subSet pour récupérer tous les mots commençant par la lettre désirée et faire un aléatoire sur le sous-ensemble. Mais à mon avis, la meilleure façon de le faire, à cause de la quantité de données, serait d'utiliser une base de données avec des requêtes SQL au lieu de Java.

-1

L'objectif est d'augmenter votre vocabulaire en langue anglaise - ne pas augmenter votre ordinateur de vocabulaire en langue anglaise.

Si vous ne partagez pas cet objectif, pourquoi payez-vous (ou vos parents) les frais de scolarité?

+2

c'est une affectation de collège ordinaire. Et je suis assez confiant au sujet de mon anglais. Peut être fait facilement. Ecrire un code pour cela va apprendre quelque chose. :) –

+1

C'est une tâche tellement stupide que la tricherie n'est pas seulement autorisée - c'est recommandé. Je retournerais une liste de 500 profanations juste pour clarifier mon point. –

+0

Je suis d'accord avec Myth17, sonne comme une répétition. –

0

Si je fais ceci:

class LoadWords { 
    public static void main(String... args) { 
    try { 
     Scanner s = new Scanner(new File("/usr/share/dict/words")); 
     ArrayList<String> ss = new ArrayList<String>(); 
     while (s.hasNextLine()) 
     ss.add(s.nextLine()); 
     System.out.format("Read %d words\n", ss.size()); 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(System.err); 
    } 
    } 
} 

je peux courir avec java -mx16m LoadWords, ce qui limite la taille du tas Java à 16 Mo, ce qui est pas beaucoup de mémoire pour Java. Mon fichier /usr/share/dict/words contient environ 250 000 mots, il est donc peut-être un peu plus petit que le vôtre.

Vous aurez besoin d'utiliser une structure de données différente de la simple ArrayList<String> que j'ai utilisée. Peut-être un HashMap de ArrayList<String>, entré sur la lettre de départ du mot serait un bon choix de départ.

1

Espérons que cela ne gâcher votre plaisir ou quelque chose, mais si je vous je prendrais cette approche ..

Pseudo java:

abstract class Word { 
    String word; 
    char last(); 
    char first();   
} 

abstract class DynamicDictionary { 
    Map<Character,Set<Word>> first_indexed; 

    Word removeNext(Word word){ 
     Set<Word> candidates = first_indexed.get(word.last()); 
     return removeRandom(candidates); 
    } 

    /** 
    * Remove a random word out from the entire dic. 
    */ 
    Word removeRandom(); 

    /** 
    * Remove and return a random word out from the set provided. 
    */ 
    Word removeRandom(Set<Word> wordset);  
} 

puis

Word primer = dynamicDictionary.removeRandom(); 
List<Word> list = new ArrayList<Word>(500); 
list.add(primer); 
for(int i=0, Word cur = primer;i<499;i++){ 
    cur = dynamicDictionary.removeNext(cur); 
    list.add(cur); 
} 

NOTE: Non destiné à être considéré comme du code java, juste un moyen d'expliquer grossièrement l'approche (pas de gestion des erreurs, pas une bonne structure de classe si elle était vraiment utilisée, pas d'encupsulation, etc.)

Dois-je rencontrer des problèmes de mémoire, peut-être que je vais faire ceci:

abstract class Word { 
    int lineNumber; 
    char last(); 
    char first(); 
} 

Si cela ne suffit pas, suppose que je vais utiliser une recherche binaire sur le fichier ou le mettre dans un DB etc ..