В Java, как физическая память содержит хэш-карту строк длиной 1 МБ каждая? - PullRequest
1 голос
/ 02 августа 2011

Этот вопрос беспокоит меня довольно давно, и я не могу найти какой-либо ответ от оракула Java-ресурса.Кто-нибудь имеет какие-либо подсказки по этому вопросу:

Я понимаю, что строка на самом деле является массивом char.Однако мне интересно, как это отличается, когда речь идет о том, как данные хранятся в физической памяти для следующих двух случаев:

Случай 1) всего 10 строк, помещенных в хэш-карту.Каждая строка начинается с 0 длины.и каждую секунду каждая строка имеет значение append с 1000 байтов.пока он не достигнет 1 МБ каждый

Случай 2) всего 10 строк, помещенных в хэш-карту.Каждая строка начинается с 1М длины (с пробелом).и каждую секунду каждая строка имеет значение и заменяет на 1000 байтов.пока не заменил все по 1МБ каждый.

Для case1 приведет ли это к тому, что будет сделано больше ссылок на физическую память, поскольку длина строки продолжает расти, и необходимо выполнить новое выделение?или он «выталкивает» данные позади, чтобы он мог выделить следующую доступную память?

Для case2 это означает, что требуется меньше ссылок (или практически не требуется ссылка), потому что строка была инициирована с длиной 1 МБ в первомplace?

Наконец, мне интересно, как эти два случая влияют на сборщик мусора или производительность выделения памяти?

1 Ответ

4 голосов
/ 02 августа 2011

На самом деле они оба примерно одинаковы при работе со строками.

Проще говоря, строки неизменяемы.Таким образом, если у вас есть строка из 1000 символов, и вы добавляете к ней 1000 символов, то у вас есть одна строка из 2000 символов, а предыдущая доступна для сборки мусора.

Если у вас есть строка в 1 млн.и измените его, у вас есть новая строка 1M, а старая доступна для сборки мусора.Поскольку строки являются неизменяемыми, нет никакой уловки разделения старой строки, удаления того, что вы хотите, добавления новой и добавления старого и нового вместе.Скорее, он просто копирует его оптом с новой версией.

Существуют другие структуры, которые ведут себя лучше, но все еще имеют схожие проблемы.

Например, если у вас есть StringBuilder, он будет себя вестипочти так же, как обычная строка в случае 1000 + 1000.Однако, если вы знаете, что это произойдет, вы можете предварительно выделить его, скажем, 10 000, а затем он просто скопирует в заранее выделенное пространство, а не выбросит весь старый комплект.

Еще одна особенность неизменяемости строк - возможность совместного использования строк.

Простой пример:

String a = "abc123";
String b = a.substring(1, 3);

Это будет один массив из 6 символов ("abc123"), но ОБАСтрока будет указывать на этот массив, строка 'b' будет указывать на смещение в массиве от оригинала.

Недостатком этого является:

String a = ".../pinky 1 MILLION characters...";
String b = a.substr(1, 3);
a = null;

'b' теперь указываетв исходный буфер, который использовал «a», хотя он «видит» только 3 символа.Итак, ваша строка 'b' на самом деле удерживает 1 млн символов памяти.

...