Инкапсулирует Строки как байт [] для сохранения излишества памяти? (Java)

Недавно рассматривал некоторый Java код Swing и видел это:

byte[] fooReference;

String getFoo() {
   returns new String(fooReference); 
}

void setFoo(String foo) {
  this.fooReference = foo.getBytes();
}

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

Это излишество, кто-либо еще инкапсулирующий их Строки таким образом?

6
задан Eyal Schneider 29 July 2010 в 22:30
поделиться

8 ответов

Это действительно, очень плохая идея. Не используйте кодировку платформы по умолчанию. Ничего не сказано, что если вы вызовете setFoo , а затем getFoo , вы получите те же данные.

Если вы должны сделать что-то подобное, тогда используйте UTF-8, который наверняка может представлять весь Юникод ... но я бы не стал этого делать. Он потенциально экономит часть памяти, но за счет ненужного выполнения преобразований в течение большей части времени - и подвержен ошибкам, если не использовать подходящую кодировку.

Осмелюсь сказать, что есть некоторые приложения, где это было бы уместно, но для 99,99% из них это ужасная идея.

31
ответ дан 8 December 2019 в 02:03
поделиться

Это бесполезно:
1. Вы копируете строку каждый раз, когда вызываются getFoo или setFoo, что увеличивает использование ЦП и памяти
2. Непонятно

10
ответ дан 8 December 2019 в 02:03
поделиться

Небольшой исторический экскурс...

Использование байтовых массивов вместо объектов String на самом деле имело значительные преимущества в ранние дни Java (1.0/1.1), если вы могли быть уверены, что вам никогда не понадобится ничего за пределами ISO-8859-1. В виртуальных машинах того времени использование drawBytes() по сравнению с drawString() было более чем в 10 раз быстрее, и это действительно экономит память, которой в то время было очень мало, а апплеты в любом случае имели жестко закодированный барьер памяти в 32, а позже 64 МБ. Байт[] не только меньше, чем встроенный char[] объектов String, но вы также можете сэкономить сравнительно тяжелый объект String, что имело большое значение, если у вас было много коротких строк. Кроме того, доступ к простому массиву байтов также быстрее, чем использование методов доступа String со всеми их дополнительными проверками границ.

Но поскольку drawBytes перестал быть быстрее в Java 1.2 и поскольку современные JIT намного лучше, чем Symantec JIT того времени, оставшееся минимальное преимущество в производительности массивов byte[] по сравнению со строками больше не стоит того. Преимущество в памяти все еще есть, и, таким образом, это все еще может быть вариантом в некоторых очень редких экстремальных сценариях, но в настоящее время это ничто, что следует рассматривать, если это не действительно необходимо.

5
ответ дан 8 December 2019 в 02:03
поделиться

Каждый вызов getFoo () создает экземпляр новой строки. Как это экономия памяти? Во всяком случае, вы добавляете дополнительные накладные расходы для вашего сборщика мусора, чтобы он мог очистить эти новые экземпляры, когда эти новые ссылки становятся не связанными

2
ответ дан 8 December 2019 в 02:03
поделиться

Это действительно бессмысленно. Если бы это была константа времени компиляции, которую вам не нужно возвращать обратно в String , тогда было бы больше смысла в бит . У вас все еще есть проблема с кодировкой символов.

Для меня было бы больше смысла, если бы это была константа char [] . В реальном мире существует несколько компиляторов JSP, которые оптимизируют строковые константы в char [] , который, в свою очередь, можно легко записать в Writer # write (char []) . Это, наконец, «немного» более эффективно, но эти маленькие биты имеют большое значение в больших и часто используемых приложениях, таких как Google Search и т. Д.

Компилятор Tomcat JSP Джаспер также делает это. Проверьте параметр genStringAsCharArray . Тогда это будет так

static final char[] text1 = "some static text".toCharArray();

вместо

static final String text1 = "some static text";

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

2
ответ дан 8 December 2019 в 02:03
поделиться

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

3
ответ дан 8 December 2019 в 02:03
поделиться

Если после профилирования вашего кода вы обнаружите, что использование памяти для строк является проблемой, вам лучше использовать общий строковый компрессор и хранить сжатые строки, а не пытаться использовать строки UTF-8 ради незначительного сокращения пространства, которое они дают. Для англоязычных строк, как правило, можно сжать их до 1-2 бит на символ; большинство других языков, вероятно, схожи. Добиться <1 бита на символ сложно, но возможно, если у вас много данных.

1
ответ дан 8 December 2019 в 02:03
поделиться

Если вы ожидаете, что у вас будет много одинаковых строк, еще один гораздо лучший способ сэкономить память - использовать метод String.intern () .

3
ответ дан 8 December 2019 в 02:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: