Следующая информация взята из официального 1 исходного кода OpenJDK 11 2 .
Начиная с самого метода String.replaceAll
.
public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}
Кэширования здесь нет. Далее Pattern.compile
public static Pattern compile(String regex) {
return new Pattern(regex, 0);
}
Кэширования там тоже нет. И не в приватном конструкторе Pattern
.
Конструктор Pattern
использует внутренний метод compile()
для выполнения компиляции регулярного выражения во внутреннюю форму. Требуются шаги, чтобы избежать компиляции Pattern
дважды. Но, как видно из вышесказанного, каждый вызов replaceAll
генерирует один-единственный объект Pattern
.
Так почему вы видите ускорение в этих показателях производительности?
Они могут использовать старую (до Java 6) версию Pattern
, которая может иметь 3 кэшированных скомпилированных шаблонов.
Наиболее вероятное объяснение состоит в том, что это просто эффект разогрева JVM. Хорошо написанный тест должен учитывать это, но тест, который используется в этом блоге, не выполняет надлежащую прогрев.
Короче говоря, ускорение, которое вы считаете вызвано некоторой «оптимизацией», по-видимому, является просто результатом эффектов разогрева JVM, таких как JIT-компиляция Pattern
, Matcher
и связанных классов.
1 - Исходный код OpenJDK код для Java 6 и более можно загрузить с https://openjdk.java.net/
2 - Исходный код OpenJDK 6 делает то же самое: без кэширования.
3 - Я не проверял, но это спорный вопрос. Тесты производительности на основе версий EOL Java не являются поучительными для текущих версий Java. Никто не должен все еще использовать Java 5. Если это так, то производительность replaceAll
- это наименьшее из их опасений.