Как эффективно сериализовать String в существующий ByteBuffer?
Кажется, что String.getBytes()
создаст новый байтовый массив, так что будет дополнительная копия памяти. Могу ли я закодировать строку прямо в ByteBuffer
без промежуточного байтового массива?
например:
void putString(ByteBuffer bb, String s) {
byte[] arr = s.getBytes(StandardCharsets.UTF_8);
bb.put(arr);
}
Этот фрагмент кода создаст байтовый массив, закодирует строку в этот байтовый массив, а затем скопирует содержимое байтового массива в ByteBuffer. Я думаю, что массив байтов не нужен, он принесет GC и дополнительную копию памяти.
4 ответа
Ты можешь использовать CharsetEncoder
написать прямо в ByteBuffer
:
static void putString(ByteBuffer buffer, String str, Charset charset) {
CharsetEncoder encoder = charset.newEncoder();
encoder.encode(CharBuffer.wrap(str), buffer, true);
encoder.flush(buffer);
}
Это ваша ответственность, чтобы убедиться, что достаточно места было выделено. Вы также можете проверить результат encode()
метод, чтобы увидеть, если это было успешно.
Я не могу придумать простой способ полностью исключить промежуточные байтовые массивы.
Однако, если вы беспокоитесь об этом, потому что строка огромна, вы можете разбить ее на куски:
for(offset=0; offset<str.length(); offset+=chunkSize) {
String chunk = str.substring(offset, offset+chunkSize);
byteBuffer.put(chunk.getBytes(StandardCharsets.UTF_8));
}
Однако, если ваши входные строки достаточно велики, чтобы эта оптимизация была необходима, общая архитектура вашей программы, вероятно, неверна.
Вам не следует беспокоиться о производительности GC, если вы не увидели чего-то необычного во время профилирования. JRE великолепен в эффективном GC.
Строковые объекты неизменны по назначению. Вся идея этого класса состоит в том, чтобы не позволять манипулировать какими-либо базовыми структурами данных (в основном по соображениям безопасности и оптимизации производительности).
В этом смысле: нет другого лучшего подхода для получения байтов, составляющих строковый объект в Java.