Я думаю, вы могли бы добиться большего успеха, чем с помощью HashMap.
Пища для размышлений по решению hashmap
Ваш ответ приемлем, но учтите: для простоты давайте предположим, что вы читаете файл по одному байту за раз в StringBuffer, пока не попадете в пробел. В этот момент вы вызовете toString (), чтобы преобразовать StringBuffer в String. Затем вы проверяете, находится ли строка в HashMap и будет ли она сохранена или счетчик будет увеличен.
Английский дик. Включенный в Linux имеет 400 тыс. слов и составляет около 5 МБ. Итак, из «1 ГБ» текста, который вы прочитали, мы можем предположить, что вы будете хранить только около 5 МБ в вашем HashMap. Оставшаяся часть файла будет преобразована в строки, которые нужно будет собрать в мусор после того, как вы поищете их на своей карте. Я могу ошибаться, но я полагаю, что байты будут повторяться снова во время создания String, поскольку массив байтов необходимо копировать внутренне и снова для вычисления HashCode. Таким образом, решение может тратить значительное количество циклов ЦП и заставлять GC часто встречаться.
Нормально указывать подобные вещи в своем интервью, даже если это единственное решение, которое вы можете придумать.
Я мог бы рассмотреть возможность использования пользовательской RadixTree или структуры, подобной Trie
Имейте в виду, как работает метод вставки RadixT / Trie. Который должен взять поток символов / байтов (обычно строку) и сравнить каждый элемент с текущей позицией в дереве. Если префикс существует, он просто перемещается вниз по дереву и потоку байтов на этапе блокировки. Когда он достигает нового суффикса, он начинает добавлять узлы в дерево. Как только достигнут конец потока, он помечает этот узел как EOW. Теперь подумайте, что мы могли бы сделать то же самое, читая намного больший поток, сбрасывая текущую позицию в корень дерева каждый раз, когда мы сталкиваемся с пробелом.
Если мы написали наше собственное дерево Radix (или, может быть, Trie), у узлов которого были счетчики конца слова (а не маркеры), и метод вставки считывался непосредственно из файла. Мы могли бы вставлять узлы в дерево по одному байту / символу за раз, пока мы не прочитаем пробел. В этот момент метод вставки увеличивает счетчик конца слова (если это существующее слово) и сбрасывает текущую позицию в дереве обратно в заголовок и снова начинает вставлять байты / символы. Принцип работы основополагающего дерева состоит в том, чтобы свернуть дублирующиеся префиксы слов. Например:
The following file:
math1 raj1 raj2 math rj2 math rj3
would be converted to:
(root)-math->1->(eow=1)
| |-(eow=2)
|
raj->1->(eow=1)
| |->2->(eow=1)
| |->3->(eow=1)
j2->(eow=1)
Время вставки в дерево, как это, будет O (k), где k - длина самого длинного слова. Но так как мы вставляем / сравниваем как мы читаем каждый байт. Мы не более неэффективны, чем просто читаем файл, как уже сделали.
Кроме того, обратите внимание, что мы будем читать байт (ы) во временный байт, который будет переменной стека, поэтому единственный раз, когда нам нужно выделить память из кучи, - это когда мы встречаем новое слово (фактически новый суффикс) , Следовательно, сборка мусора происходит не так часто. И общая память, используемая деревом Radix, будет намного меньше, чем HashMap.