Когда вы хотите найти все анаграммы, не рекомендуется пытаться сравнивать одно слово со всеми другими словами, так как в конечном итоге вы сравниваете каждое слово с каждым другим словом, которое известно как квадратичное сложность времени . Для обработки 1000 слов вам потребуются миллионы сравнений, для обработки 100 000 слов - 10 000 000 000 сравнений и т. Д.
Вы можете изменить метод isAnagram
, чтобы обеспечить ключ поиска для структур данных, таких как HashMap
:
static CharBuffer getAnagramKey(String s) {
char[] word1 = s.replaceAll("[\\s]", "").toCharArray();
Arrays.sort(word1);
return CharBuffer.wrap(word1);
}
Класс CharBuffer
оборачивает массив char[]
и предоставляет необходимые методы equals
и hashCode
без копирования содержимого массива, что делает его предпочтительным для создания нового String
.
В качестве примечания, .replaceAll("[\\s]", "")
можно было бы упростить до .replaceAll("\\s", "")
, и то, и другое исключило бы все пробельные символы, но пример ввода вашего вопроса вообще не имеет пробельных символов. Чтобы удалить все несловарные символы, такие как апострофы и амперсанды, вы можете использовать s.replaceAll("\\W", "")
.
Затем вы можете обработать все слова, чтобы найти анаграммы за один линейный проход, например
URL srcURL = new URL("http://wiki.puzzlers.org/pub/wordlists/unixdict.txt");
try(InputStream is = srcURL.openStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
Stream<String> stream = reader.lines()) {
stream.collect(Collectors.groupingBy(s -> getAnagramKey(s)))
.values().stream()
.filter(l -> l.size() > 1)
.forEach(System.out::println);
}
С этим решением печать, вероятно, становится более дорогой частью для больших списков слов. Таким образом, вы можете изменить операцию потока, например, следующая команда печатает десятку комбинаций анаграмм:
stream.collect(Collectors.groupingBy(s -> getAnagramKey(s)))
.values().stream()
.filter(l -> l.size() > 1)
.sorted(Collections.reverseOrder(Comparator.comparingInt(List::size)))
.limit(10)
.forEach(System.out::println);