Java 解析百万字的文档

Java 解析百万字的文档,java,Java,我已经实现了一些代码来在txt sample.txt文件中查找字谜词,并在控制台上输出它们。txt文档的每一行都包含字符串 如果我想在txt.file中找到有一百万或200亿个单词的字谜单词,那么这是正确的方法吗?如果没有,在这种情况下我应该使用哪种技术 谢谢你的帮助 样品 奥普特 代码 对于200亿个单词,您将无法将它们全部保存在RAM中,因此您需要一种方法将它们分块处理 200亿字。Java需要相当多的内存来存储字符串,因此每个字符可以计算2个字节,开销至少为38个字节 这意味着一个字符的2

我已经实现了一些代码来在txt sample.txt文件中查找字谜词,并在控制台上输出它们。txt文档的每一行都包含字符串

如果我想在txt.file中找到有一百万或200亿个单词的字谜单词,那么这是正确的方法吗?如果没有,在这种情况下我应该使用哪种技术

谢谢你的帮助

样品

奥普特

代码


对于200亿个单词,您将无法将它们全部保存在RAM中,因此您需要一种方法将它们分块处理

200亿字。Java需要相当多的内存来存储字符串,因此每个字符可以计算2个字节,开销至少为38个字节

这意味着一个字符的20000000个字需要8000000000字节或800GB,这比我所知道的任何计算机都要多


您的文件将包含远少于20000000个不同的单词,因此,如果您只将每个单词存储一次(例如在一个集合中),您可能会避免内存问题。

对于200亿个单词,您将无法将它们全部保存在RAM中,因此您需要一种方法来分块处理它们

200亿字。Java需要相当多的内存来存储字符串,因此每个字符可以计算2个字节,开销至少为38个字节

这意味着一个字符的20000000个字需要8000000000字节或800GB,这比我所知道的任何计算机都要多

您的文件将包含远少于20000000个不同的单词,因此,如果您只将每个单词存储一次(例如在一个集合中),则可以避免内存问题

更新

您可以使用地图来查找下面的字谜。对于您拥有的每个单词,您可以对其字符进行排序,并获得一个已排序的字符串。所以,这将是你的字谜图的关键。这个键的值将是其他的字谜词

public void findAnagrams(String[] yourWords) {
    Map<String, List<String>> anagrams = new HashMap<String, List<String>>();
    for (String word : yourWords) {
        String sortedWord = sortedString(word);
        List<String> values = anagrams.get(sortedWord);
        if (values == null) 
            values = new LinkedList<>();

        values.add(word);
        anagrams.put(sortedWord, values);
    }

    System.out.println(anagrams);
}

private static String sortedString(String originalWord) {

    char[] chars = originalWord.toCharArray();
    Arrays.sort(chars);
    String sorted = new String(chars);
    return sorted;
}
更新

您可以使用地图来查找下面的字谜。对于您拥有的每个单词,您可以对其字符进行排序,并获得一个已排序的字符串。所以,这将是你的字谜图的关键。这个键的值将是其他的字谜词

public void findAnagrams(String[] yourWords) {
    Map<String, List<String>> anagrams = new HashMap<String, List<String>>();
    for (String word : yourWords) {
        String sortedWord = sortedString(word);
        List<String> values = anagrams.get(sortedWord);
        if (values == null) 
            values = new LinkedList<>();

        values.add(word);
        anagrams.put(sortedWord, values);
    }

    System.out.println(anagrams);
}

private static String sortedString(String originalWord) {

    char[] chars = originalWord.toCharArray();
    Arrays.sort(chars);
    String sorted = new String(chars);
    return sorted;
}

首先是一个较小的数字

由于最好使用更强大的数据结构,所以不要读取核心中的所有行,而是逐行读取

Map<String, Set<String>> mapSortedToWords = new HashMap<>();

Path path = Paths.get(fileName);
try (BufferedReader in = Files.newBufferedReader(Path, StandardCharsets.UTF_8)) {
    for (;;) {
        String word = in.readLine();
        if (word == null) {
            break;
        }
        String key = sorted(word);
        Set<String> words = mapSortedToWords.get(key);
        if (words == null) {
            words = new TreeSet<String>();
            mapSortedToWords.put(key, words);
        }
        words.add(word);
    }
}
for (Set<String> anagrams : mapSortedToWords.values()) {
    if (anagrams.size() > 1) {
        ... anagrams
    }
}

static String sorted(String word) {
    char[] letters = word.toCharArray();
    Arrays.sort(letters);
    return new String(letters);
}
这将在地图中存储一组单词。可与abac aabc abca媲美


对于存储sortedLetters的大量数据库,word会更好。像Derby或H2这样的嵌入式数据库不会造成安装问题。

首先是针对较小数量的数据库

由于最好使用更强大的数据结构,所以不要读取核心中的所有行,而是逐行读取

Map<String, Set<String>> mapSortedToWords = new HashMap<>();

Path path = Paths.get(fileName);
try (BufferedReader in = Files.newBufferedReader(Path, StandardCharsets.UTF_8)) {
    for (;;) {
        String word = in.readLine();
        if (word == null) {
            break;
        }
        String key = sorted(word);
        Set<String> words = mapSortedToWords.get(key);
        if (words == null) {
            words = new TreeSet<String>();
            mapSortedToWords.put(key, words);
        }
        words.add(word);
    }
}
for (Set<String> anagrams : mapSortedToWords.values()) {
    if (anagrams.size() > 1) {
        ... anagrams
    }
}

static String sorted(String word) {
    char[] letters = word.toCharArray();
    Arrays.sort(letters);
    return new String(letters);
}
这将在地图中存储一组单词。可与abac aabc abca媲美


对于存储sortedLetters的大量数据库,word会更好。像Derby或H2这样的嵌入式数据库不会造成安装问题。

使用流读取文件。这样,一次只存储一个单词

FileReader file = new FileReader("file.txt"); //filestream

String word;

while(file.ready()) //return true if there a bytes left in the stream
{
    char c = file.read(); //reads one character
    if(c != '\n') 
    {
        word+=c;
    }
    else {
    process(word); // do whatever you want
    word = "";
    }
}

使用流读取文件。这样,一次只存储一个单词

FileReader file = new FileReader("file.txt"); //filestream

String word;

while(file.ready()) //return true if there a bytes left in the stream
{
    char c = file.read(); //reads one character
    if(c != '\n') 
    {
        word+=c;
    }
    else {
    process(word); // do whatever you want
    word = "";
    }
}

对于指定的200亿字的文件大小,显然代码存在两个主要问题

List<String> list = Files.readAllLines(Paths.get(fileName)); 

你们节目中的这两行基本上是问题

您是否有足够的内存一次性读取完整文件? 迭代200亿次可以吗? 对于大多数系统,上述两个问题的答案都是否定的

因此,您的目标是减少内存足迹并减少迭代次数

因此,您需要逐块读取文件,并使用某种搜索数据结构(如存储单词)

对于上述两个主题,您会发现许多问题

上面的算法说,您必须首先为您的单词创建一个字典

无论如何,我相信没有现成的答案给你。拿一个10亿字的文件来说,这本身就是一个非常困难的任务,看看什么能工作,什么不能工作,但是你当前的代码显然不能工作


希望能有帮助

对于您指定的200亿字的文件大小,显然您的代码存在两个主要问题

List<String> list = Files.readAllLines(Paths.get(fileName)); 

你们节目中的这两行基本上是问题

您是否有足够的内存一次性读取完整文件? 迭代200亿次可以吗? 对于大多数系统,上述两个问题的答案都是否定的

因此,您的目标是减少内存足迹并减少迭代次数

因此,您需要逐块读取文件,并使用某种搜索数据结构(如存储单词)

对于上述两个主题,您会发现许多问题

上面的算法说,您必须首先为您的单词创建一个字典

无论如何,我相信没有现成的答案给你。拿一个10亿字的文件来说,这本身就是一个非常困难的任务,看看什么是有效的,什么是d oesn不能,但您当前的代码显然无法工作


希望能有帮助

一个数据库,带有一些函数是一种策略,因为你要比较每个条目和其他条目,这种方法非常慢。不要直接比较它们,而是通过分组进行比较。使用键代表某个字谜组的映射,在本例中,预排序字符串aabc代表aabc、abac、caba等组。然后,值要么是该组的每个项目的列表/集合,要么是用于写入值的文件处理程序,以避免将它们保留在内存中。一个带有某些函数的db是一种策略,因为您要将每个条目与可能的每个其他条目进行比较,这种方法非常慢。不要直接比较它们,而是通过分组进行比较。使用键代表某个字谜组的映射,在本例中,预排序字符串aabc代表aabc、abac、caba等组。然后,该值要么是该组的每个项目的列表/集合,要么是用于写入值的文件处理程序,以避免将它们保留在内存中。整数应该是什么?字符串不是更直观吗?那字符串是什么?如果有acab、abac、baac和caab,您会选择哪一个作为密钥?我认为整数作为键可能更合适。在本例中,字谜图看起来像{7,[acab,abac,baac,caab]}您会选择哪一个显然是aabc,因为这是每个组合有两个a,一个b和一个c的字谜组的预排序代表,并且因为OP对字符数组进行排序。在你的例子中,7是什么?为什么不是8点或42点?我现在明白你的意思了。谢谢我很快会更新我的答案。int的问题是,如果你用每个字符的值来计算键,那么就有可能得到具有不同字符串的相等键,比如ac和bb,它们都有附加值196。您需要某种无冲突的哈希代码。我想字符串比较简单。整数应该是什么?字符串不是更直观吗?那字符串是什么?如果有acab、abac、baac和caab,您会选择哪一个作为密钥?我认为整数作为键可能更合适。在本例中,字谜图看起来像{7,[acab,abac,baac,caab]}您会选择哪一个显然是aabc,因为这是每个组合有两个a,一个b和一个c的字谜组的预排序代表,并且因为OP对字符数组进行排序。在你的例子中,7是什么?为什么不是8点或42点?我现在明白你的意思了。谢谢我很快会更新我的答案。int的问题是,如果你用每个字符的值来计算键,那么就有可能得到具有不同字符串的相等键,比如ac和bb,它们都有附加值196。您需要某种无冲突的哈希代码。我想字符串会更简单。史密斯先生是对的,如果您不确定要处理的单词的实际数量,最好将文件分块读取。例如,您可以逐行读取文件。第一次实例化扫描仪:scanner scanner=new ScannerfileName;第二,用whilescanner.hasNextLine替换for循环{然后用String word=scanner.nextLine读取每个单词;但这样,您就没有要比较的单词列表。因此,您可能必须找到另一种方法来检查一个单词是否为字谜。要处理数十亿个单词,是否可以将数据存储在服务器上的数据库中,然后用MySQL查询它们?是数据库还是我们e文件系统。例如,您可以将文件拆分为每个文件中都有一个特定长度的所有单词的文件。字谜只能存在于相同长度的单词中。如果文件中仍有太多单词无法在RAM中处理,您可以考虑其他方法将问题拆分为更小的部分。如果您不确定但对于您要处理的实际字数,最好将文件分块读取。例如,您可以逐行读取文件。首先实例化扫描仪:scanner scanner=new ScannerfileName;其次将for循环替换为whilescanner.hasNextLine{然后用String word=scanner.nextLine读取每个单词;但这样,您就没有要比较的单词列表。因此,您可能必须找到另一种方法来检查一个单词是否为字谜。要处理数十亿个单词,是否可以将数据存储在服务器上的数据库中,然后用MySQL查询它们?是数据库还是我们e文件系统。例如,你可以将你的文件拆分为每个文件都有一个特定长度的所有单词的文件。字谜只能存在于相同长度的单词中。如果文件中包含的单词仍然太多,无法在RAM中处理,你可以考虑其他方法将问题拆分为更小的部分。如我在评论中所述,OP也可以使用filehandler作为映射值,将每个项目写入一个文件,而不是将其保存在ram中(如果他真的读取)
这是巨大的文件。但是,对于较小的文件,一个集合是合适的。我喜欢,我们的想法是一样的:D.正如我在评论中所写的,OP也可以使用filehandler作为映射值,将每个项目写入一个文件,而不是将其保存在ram中,如果他真的读取大文件。但是,对于较小的文件,一个集合是合适的。我喜欢,我们有相同的想法:D。