Найти дубликаты в большом файле

У меня действительно большой файл с примерно 15 миллионами записей. Каждая строка файла содержит одну строку (назовите ее).

Мне нужно найти дубликаты записей в файле с помощью java. Я попытался использовать хэш-карту и обнаружить повторяющиеся записи. По-видимому, этот подход бросает мне ошибку "java.lang.OutOfMemoryError: Java heap space".

Как я могу решить эту проблему?

Я думаю, что я мог бы увеличить кучу пространства и попробовать, но я хотел знать, есть ли более эффективные решения без необходимости изменять область кучи.

Ответ 1

Ключ в том, что ваши данные не будут вписываться в память. Вы можете использовать внешнюю сортировку слияния для этого:

Разделите свой файл на несколько меньших фрагментов, которые вписываются в память. Сортируйте каждый кусок, устраните дубликаты (теперь соседние элементы).

Объедините куски и снова удалите дубликаты при слиянии. Так как у вас будет n-nway merge здесь, вы можете сохранить следующие k-элементы из каждого фрагмента в памяти, как только элементы для фрагмента исчерпаны (они уже были объединены) захватывают больше с диска.

Ответ 2

Я не уверен, что вы решили сделать это за пределами java, но если это так, это очень просто в оболочке:

cat file | sort | uniq

Ответ 3

Вероятно, вы не можете загрузить весь файл за один раз, но вы можете сохранить хэш и номер строки в HashSet без проблем.

Псевдокод...

for line in file
    entries.put(line.hashCode, line-number)
for entry in entries
    if entry.lineNumbers > 1
         fetch each line by line number and compare

Ответ 4

Я не думаю, что вам нужно сортировать данные для устранения дубликатов. Просто используйте метод quicksort inspired.

  • Выберите k значений из данных (если ваши данные не являются обманчивыми, это должно быть довольно простым).
  • Используя эти k pivots, разделите данные на k + 1 небольшие файлы
  • Если какой-либо из этих фрагментов слишком велик, чтобы вписаться в память, повторите процесс только для этого фрагмента
  • Как только вы управляете размерными кусками, примените свой любимый метод (хеширование?), чтобы найти дубликаты.

Заметим, что k может быть равно 1.

Ответ 5

Один из способов, которым я могу себе представить, - это сначала использовать внешний алгоритм сортировки для сортировки файла (поиск external sort java дает много результаты с кодом). Затем вы можете итерировать файл по строкам, теперь дубликаты будут явно следовать друг за другом, поэтому вам нужно только запомнить предыдущую строку во время итерации.

Ответ 6

Если вы не можете создать полный список, так как у вас недостаточно памяти, вы можете попробовать сделать это в циклах. То есть создайте хэш-карту, но только сохраните небольшую часть элементов (например, те, которые начинаются с A). Затем вы собираете дубликаты, затем продолжаете "B" и т.д.

Конечно, вы можете выбрать любую "группировку" (т.е. первые 3 символа, первые 6 и т.д.).

Это займет всего несколько итераций.

Ответ 7

Вы можете попробовать Bloom filter, если вы готовы принять определенную статистическую ошибку. Guava предоставляет один, но в этом есть довольно большая ошибка, которая должна быть исправлена, вероятно, на следующей неделе с выпуском 11.0.2.