Java:从一个大文件中获取随机行

时间:2011-10-01 21:34:45

标签: java file constraints

我见过how to get a random line from a text file,但那里所说的方法(接受的答案)运行速度非常慢。它在我的598KB文本文件上运行得非常慢,并且在我的一个文本文件版本上仍然很慢,该文本文件只有20行中每20行中有一行。我从未超越“a”部分(这是一个单词表)。

原始文件有64141行;缩短的有2138行。为了生成这些文件,我使用Linux Mint 11 /usr/share/dict/american-english wordlist并使用grep删除任何带有大写或撇号(grep -v [[:upper:]] | grep -v \')的内容。

我正在使用的代码是

String result = null;
final Random rand = new Random();
int n = 0;
for (final Scanner sc = new Scanner(wordList); sc.hasNext();) {
    n++;
    if (rand.nextInt(n) == 0) {
    final String line = sc.nextLine();
        boolean isOK = true;
        for (final char c : line.toCharArray()) {
            if (!(constraints.isAllowed(c))) {
                isOK = false;
                break;
            }
        }
        if (isOK) {
            result = line;
        }
        System.out.println(result);
    }
}
return result;

略微改编自Itay's answer

对象constraintsKeyboardConstraints,基本上有一种方法isAllowed(char)

public boolean isAllowed(final char key) {
    if (allAllowed) {
        return true;
    } else {
        return allowedKeys.contains(key);
    }
}

其中allowedKeysallAllowed在构造函数中提供。此处使用的constraints变量"aeouhtns".toCharArray()allowedKeysallAllowed关闭。

基本上,我希望方法做的是选择满足约束的随机词(例如,对于这些约束,“outvote”会起作用,但不是“worker”,因为“w” “不在"aeouhtns".toCharArray())。

我该怎么做?

2 个答案:

答案 0 :(得分:3)

您的实施中存在错误。您应该在选择随机数之前阅读该行。改变这个:

n++;
if (rand.nextInt(n) == 0) {
    final String line = sc.nextLine();

对此(如original answer):

n++;
final String line = sc.nextLine();
if (rand.nextInt(n) == 0) {

您还应该在绘制随机数之前检查约束。如果一行不通过约束,则应忽略它,如下所示:

n++;

String line;
do {
    if (!sc.hasNext()) { return result; }
    line = sc.nextLine();
} while (!meetsConstraints(line));

if (rand.nextInt(n) == 0) {
    result = line; 
}

答案 1 :(得分:2)

我会阅读所有行,将它们保存在某处,然后从中选择一条随机行。这需要花费大量的时间,因为这些天小于1 MB的单个文件很小。

public class Main {
    public static void main(String... args) throws IOException {
        long start = System.nanoTime();
        RandomDict dict = RandomDict.load("/usr/share/dict/american-english");
        final int count = 1000000;
        for (int i = 0; i < count; i++)
            dict.nextWord();
        long time = System.nanoTime() - start;
        System.out.printf("Took %.3f seconds to load and find %,d random words.", time / 1e9, count);
    }
}

class RandomDict {
    public static final String[] NO_STRINGS = {};
    final Random random = new Random();
    final String[] words;

    public RandomDict(String[] words) {
        this.words = words;
    }

    public static RandomDict load(String filename) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader(filename));
        Set<String> words = new LinkedHashSet<String>();
        try {
            for (String line; (line = br.readLine()) != null; ) {
                if (line.indexOf('\'') >= 0) continue;
                words.add(line.toLowerCase());
            }
        } finally {
            br.close();
        }
        return new RandomDict(words.toArray(NO_STRINGS));
    }

    public String nextWord() {
        return words[random.nextInt(words.length)];
    }
}

打印

Took 0.091 seconds to load and find 1,000,000 random words.