У меня огромные ГБ данных для чтения, и если я использую String, у меня заканчивается куча данных.
Тогда вам придется думать о другом.
Вы можете использовать TreeMap<char[], V>
с пользовательским Comparator
... но это мера с ограничением.
Вы могли бы реализовать пользовательский класс Map
на основе хеш-таблицы, который использовал бы char[]
в качестве ключа, но выполнял тесты хэширования и равенства массива без использования ключевого объекта equals(Object)
и hashcode()
методы.Это также является мерой с ограничением зазора.
Вы можете получить машину большего размера ... еще одну меру с ограничением зазора.
Вы можетеПерепроектируйте алгоритм так, чтобы ему не приходилось помещать все данные в большую хэш-таблицу в памяти в адресном пространстве одной Java-программы.
То, что вы сейчас делаетене масштабируетсяДаже если вам удастся реализовать карту с помощью клавиш char[]
вместо клавиш String
, вы, вероятно, только уменьшите пространство, используемое для удержания клавиш, наполовину.Лучшее, что это даст вам, - это способность обрабатывать примерно вдвое больше ключей, чем вы в настоящее время можете обрабатывать.Затем вы снова попадаете в стену.
В долгосрочной перспективе последний вариант является наилучшим, если вы хотите продолжать увеличиваться.
Кстати, предложение @Sean Patrick Floyd о стажировкеключевые строки, вероятно, только усугубят ситуацию.Во-первых, вы никогда не получите строки, которые равны, но не == как ключи на одной карте.Так что интернирование ничего не спасает.Во-вторых, интернирование выполняется с использованием закрытой хеш-таблицы, и JVM необходимо выделить пространство для представления этой таблицы.
Единственный сценарий, в котором интернирование потенциально целесообразно, - это если строки, которые вы используете для выполнения поиска по картескорее всего переживет несколько циклов GC.Только тогда может сохранить пространство.
Наконец, есть один сценарий, который может привести к тому, что ваши ключевые строки будут использовать гораздо больше памяти, чем вы думаете.Примите во внимание следующее:
BufferedReader br = ...
Map<String, Value> map = new HashMap<String, Value>();
String line;
while ((line = br.readLine()) != null) {
...
String key = line.substring(...);
map.put(key, ...);
}
Проблема в том, что метод substring
имеет ту же основу char[]
, что и исходная строка.Если key
является долгоживущим (что, вероятно, будет), это означает, что исходный большой резервный массив также будет долгоживущим, даже если мы только когда-либо будем ссылаться на фрагмент этого массива через key
object.
Решение состоит в том, чтобы написать это:
String key = new String(line.substring(...));
, что вызывает копирование символов в новый (меньший) массив символов.
ОБНОВЛЕНИЕ - Изменения в реализации java.lang.String
в Java 7 решают эту проблему.Методы substring
теперь делают копию соответствующего среза резервного массива.