Подтвердить что ты не робот

Java 7 String - сложность подстроки

До Java 6 у нас была константная подстрока времени на String. В Java 7, почему они решили пойти с копированием массива char и унизили до линейной временной сложности, когда что-то вроде StringBuilder предназначалось именно для этого?

4b9b3361

Ответ 1

Почему они решили обсудить в Ошибка Oracle # 4513622: (str) сохранение подстроки поля предотвращает GC для объекта:

Когда вы вызываете String.substring, как в примере, новый массив символов для хранения не выделяется. Он использует массив символов исходной строки. Таким образом, массив символов, поддерживающий исходную строку, не может быть GC'd, пока ссылки подстроки также не будут GC'd. Это преднамеренная оптимизация для предотвращения чрезмерных распределений при использовании подстроки в общих сценариях. К сожалению, проблемный код попадает в случай, когда заметные издержки исходного массива заметны. Трудно оптимизировать для обоих случаев краев. Любая оптимизация для компромиссов пространства/размера обычно сложна и часто может быть специфичной для платформы.

Также этот примечание, отмечая, что однажды оптимизация стала пессимизацией в соответствии с тестами:

В течение длительного времени были подготовлены и строганы для удаления полей смещения и подсчета из java.lang.String. Эти два поля позволяют нескольким экземплярам String совместно использовать один и тот же базовый буфер символов. Общие буферы символов были важной оптимизацией для старых тестов, но с текущим кодом реального мира и эталонами на самом деле лучше не разделить буферные буферы. Общий char буфер поддержки массива только "выигрывает" с очень интенсивным использованием String.substring. В ситуации с отрицательным воздействием могут присутствовать парсеры и компиляторы, однако текущее тестирование показывает, что в целом это изменение выгодно.

Ответ 2

Если у вас длинная жилая небольшая подстрока короткоживущей большой родительской строки, то большая char [], поддерживающая родительскую строку, не будет иметь права на сбор мусора, пока малая подстрока не выйдет за рамки. Это означает, что подстрока может занимать гораздо больше памяти, чем люди ожидают.

Единственный раз, когда метод Java 6 выполнялся значительно лучше, когда кто-то взял большую подстроку из большой родительской строки, что очень редко.

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

Ответ 3

Это будет влиять на сложность структур данных, таких как массивы суффикса, с достаточной долей. Java должен предоставить альтернативный метод для получения части исходной строки.

Ответ 4

Это просто их дерьмовый способ установить некоторые ограничения на сбор мусора JVM.

Перед Java 7, если мы хотим избежать неработающей проблемы с сборкой мусора, мы всегда можем скопировать подстроку вместо сохранения ссылки подстроки. Это был просто дополнительный вызов конструктору копирования:

String smallStr = new String(largeStr.substring(0,2));

Но теперь у нас больше нет подстроки с постоянным временем. Какая катастрофа.

Ответ 5

Главной мотивацией, я считаю, является "совместное размещение" String и его char[]. Прямо сейчас они располагаются на расстоянии, что является серьезным штрафом в строках кэша. Если каждому String принадлежит свой char[], JVM может объединить их вместе, а чтение будет намного быстрее.