Второй брат, в этом году я второкурсник. Я прочитал отрывок в «Руководстве по разработке Java для Alibaba», которым вы поделились: «В теле цикла лучше всего использовать метод добавления StringBuilder вместо оператора + для сращивание строк». Почему? Ах, оператор «+», который я обычно использую все время! Когда второй брат будет свободен, вы можете написать статью, чтобы проанализировать его?
Буквально вчера читатель по имени Сяокай произнес это предложение в WeChat.
Мое первое впечатление, когда я увидел это сообщение WeChat, было: Сяокай, ты слишком хорош, я не знаю почему! Думаю, вы, читающие это, почувствуете то же самое.
Но спросите себя, вяВ первые два года работы программистом я не знаю почему. встретитьсянитьОператор «+» используется для склейки вне зависимости от того, находится он в теле цикла или нет. По сравнению с Xiaocai, мне не так повезло, как ему в то время, и был восторженный «второй брат», который смог поделиться этим бесценным руководством по разработке.
Раз я с таким энтузиазмом делюсь, лучше хорошему человеку делать это до конца, правда? Я напишу статью серьезно и запутаю Xiaocai.
01. Оператор "+"
Говоря о позе, оператор «+» должен быть наиболее часто используемым для конкатенации строк, никто.
String chenmo = "沉默";
String wanger = "王二";
System.out.println(chenmo + wanger);
Давайте декомпилируем этот код с помощью JAD.
String chenmo = "\u6C89\u9ED8"; // 沉默
String wanger = "\u738B\u4E8C"; // 王二
System.out.println((new StringBuilder(String.valueOf(chenmo))).append(wanger).toString());
Зашел, оказалось, что оператор "+" был заменен на метод append StringBuilder при компиляции. То есть оператор «+» — это просто формализм при конкатенации строк, что упрощает использование разработчиками, код выглядит лаконичнее, а чтение более плавным. Это синтаксический сахар для Java.
02. Построитель строк
За исключением оператора «+», метод добавления StringBuilder является второй часто используемой позой сращивания строк.
Давайте посмотрим на исходный код метода append класса StringBuilder:
public StringBuilder append(String str) {
super.append(str);
return this;
}
В этих 3-х строках кода ничего не видно, вы видите только метод append родительского класса AbstractStringBuilder:
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
1) Определите, является ли конкатенированная строка нулевой, и если да, обработайте ее как строку «нулевая».appendNull
Исходный код метода выглядит следующим образом:
private AbstractStringBuilder appendNull() {
int c = count;
ensureCapacityInternal(c + 4);
final char[] value = this.value;
value[c++] = 'n';
value[c++] = 'u';
value[c++] = 'l';
value[c++] = 'l';
count = c;
return this;
}
2) Превышает ли длина склеиваемого массива символов текущее значение, если да, то расширяем и копируем.ensureCapacityInternal
Исходный код метода выглядит следующим образом:
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
3) Скопируйте объединенную строку str в значение целевого массива.
str.getChars(0, len, value, count)
03. Строковый буфер
Сначала идет StringBuffer, а затем StringBuilder. Они как близнецы. У них есть все, что им нужно, но старший брат StringBuffer является потокобезопасным, потому что он дышит еще двумя глотками свежего воздуха.
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
В методе append класса StringBuffer синхронизировано на одно ключевое слово больше, чем в StringBuilder, которое пока можно игнорировать.toStringCache = null
.
Synchronized — это очень знакомое ключевое слово в Java, которое является своего рода блокировкой синхронизации. Методы, которые он украшает, называются синхронизированными методами и являются потокобезопасными.
04. Метод concat класса String
Только с точки зрения положения метод concat класса String подобен методу append класса StringBuilder.
String chenmo = "沉默";
String wanger = "王二";
System.out.println(chenmo.concat(wanger));
Во время написания этой статьи мне вдруг пришла в голову замечательная идея. Если есть две строки кода, как это:
chenmo += wanger
chenmo = chenmo.concat(wanger)
Насколько велика между ними разница?
Мы научились до этого,chenmo += wanger
на самом деле эквивалентно(new StringBuilder(String.valueOf(chenmo))).append(wanger).toString()
.
Чтобы изучить оператор "+" иconcat
Разница между ними на самом деле зависит от разницы между методом append и методом concat.
Исходный код метода append был проанализирован ранее. Давайте посмотрим на исходный код метода concat.
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
int len = value.length;
char buf[] = Arrays.copyOf(value, len + otherLen);
str.getChars(buf, len);
return new String(buf, true);
}
1) Если длина объединенной строки равна 0, вернуть строку перед объединением.
if (otherLen == 0) {
return this;
}
2) Скопируйте значение массива символов исходной строки в массив переменной buf.
char buf[] = Arrays.copyOf(value, len + otherLen);
3) Скопируйте объединенную строку str в массив символов buf и верните новый строковый объект.
str.getChars(buf, len);
return new String(buf, true);
Проанализировав исходный код, мы можем примерно сделать следующие выводы:
1) Если конкатенированная строка имеет значение null, при объединении будет выдано исключение NullPointerException, а оператор «+» будет рассматриваться как «нулевая» строка.
2) Если конкатенированная строка является пустой строкой (""), то конкатенация более эффективна. Ведь не надоnew StringBuilder
объект.
3) Если конкатенированных строк много, эффективность concat снизится, потому что чем больше создается строковых объектов, тем больше накладные расходы.
Внимание! ! !
Слабо спросите, есть ли студенты, использующие JSP? Не допускается использование оператора «+» для объединения строк в выражениях EL.concat
.
${chenmo.concat('-').concat(wanger)}
05. Метод соединения класса String
JDK 1.8 предоставляет новый жест конкатенации строк: класс String добавляет соединение статического метода.
String chenmo = "沉默";
String wanger = "王二";
String cmower = String.join("", chenmo, wanger);
System.out.println(cmower);
Первый параметр — это конкатенатор строк, например:
String message = String.join("-", "王二", "太特么", "有趣了");
Вывод: Ван Эр - слишком особенный - интересный
Давайте посмотрим на исходный код метода соединения:
public static String join(CharSequence delimiter, CharSequence... elements) {
Objects.requireNonNull(delimiter);
Objects.requireNonNull(elements);
// Number of elements not likely worth Arrays.stream overhead.
StringJoiner joiner = new StringJoiner(delimiter);
for (CharSequence cs: elements) {
joiner.add(cs);
}
return joiner.toString();
}
Нашел новый класс StringJoiner, имя класса похоже на 6, и его легко читать. StringJoiner этоjava.util
Класс в пакете, который создает последовательность символов, повторно соединенных разделителями. Из-за ограничений по объему в этой статье не будет слишком много информации, и заинтересованные студенты могут узнать об этом.
06. StringUtils.join
В практических проектах, когда мы имеем дело со строками, мы часто используем этот класс——org.apache.commons.lang3.StringUtils
, метод соединения этого класса представляет собой новую позу для конкатенации строк.
String chenmo = "沉默";
String wanger = "王二";
StringUtils.join(chenmo, wanger);
Этот метод лучше подходит для объединения строк в массив, и ему не нужно беспокоиться об исключении NullPointerException.
StringUtils.join(null) = null
StringUtils.join([]) = ""
StringUtils.join([null]) = ""
StringUtils.join(["a", "b", "c"]) = "abc"
StringUtils.join([null, "", "a"]) = "a"
Глядя на исходный код, мы можем обнаружить, что StringBuilder все еще используется внутри.
public static String join(final Object[] array, String separator, final int startIndex, final int endIndex) {
if (array == null) {
return null;
}
if (separator == null) {
separator = EMPTY;
}
final StringBuilder buf = new StringBuilder(noOfItems * 16);
for (int i = startIndex; i < endIndex; i++) {
if (i > startIndex) {
buf.append(separator);
}
if (array[i] != null) {
buf.append(array[i]);
}
}
return buf.toString();
}
Когда все это читают, у всех возникает одно и то же чувство: я полагаюсь на (звук будет долгим), не ожидал, не ожидал, есть 6 видов поз для сращивания струн, я должен попробовать их один за другим, когда я вернусь домой ночью.
07. Дайте посуде ответ
Думаю, когда Сяокай прочитает мою статью, он поймет, почему Alibaba не рекомендует использовать оператор «+» для конкатенации строк в циклах for.
Давайте посмотрим на два фрагмента кода.
В первом абзаце в цикле for используется оператор «+».
String result = "";
for (int i = 0; i < 100000; i++) {
result += "六六六";
}
Во втором абзаце добавление используется в цикле for.
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100000; i++) {
sb.append("六六六");
}
Сколько времени займут эти две части кода? Результаты тестирования на моем iMac:
1) Время выполнения первого куска кода 6212 миллисекунд
2) Время выполнения второго куска кода 1 миллисекунда
Разница слишком большая! Зачем?
Я полагаю, что у многих студентов уже есть свои ответы: в цикле for первого абзаца создается большое количество объектов StringBuilder, а во втором абзаце кода только один объект StringBuilder от начала до конца.
08. Наконец
Спасибо за чтение, оригинальность не так проста, просто поставьте палец вверх, если вам это нравится, это будет моей самой сильной мотивацией для написания. Если вы считаете, что статья вам немного полезна, она достаточно интересна, просто обратите внимание на мой паблик-аккаунт»Тихий король 2";Ответить"666” Есть также высококачественные обучающие видео 500G для отправки (по категориям).