String и неточный нейминг



Сегодня пост короткий, но полезный:

▪️ Увидите на простом примере, как важны имена методов

▪️ Узнаете, как оптимизировать работу со строками



Возьмём простую задачу — поменять в строке все буквы А на B. Идея подскажет три метода:

▫️ replace

▫️ replaceFirst

▫️ replaceAll



Что говорит здравый смысл? replaceFirst поменяет первую найденную букву, replace — непонятно, но вот replaceAll точно подходит, берём!



Посмотрим реализацию методов в java 11:



🔸 replace("A", "B")



Проверяет, что в строке вообще есть буквы А. Если да, создаётся новый массив символов и копируются значения исходной строки с заменой всех A на B



🔸 replaceAll("A", "B")



Раскрывается в обработчик регулярных выражений:

Pattern.compile("A").matcher(this).replaceAll("B")



🔸 replaceFirst("A", "B")



Также работает через RegEx, но заменяет только первое вхождение.



(в java 8 внутри replace тоже используются регулярки, и разница между replace и replaceAll очень туманна)



Что отсюда следует:

1️⃣ Переходите на java 11

2️⃣ Если вам не нужен функционал регулярок, используйте replace. Методы с Pattern.compile работают очень долго!

3️⃣ Давайте методам осмысленные имена. Должно быть понятно, что метод делает, и чем отличается от других. Автор методов replace* об этом не подумал, и теперь сотни проектов выбирают неподходящий вариант



Есть ли разница между replace("a", "b") и replace('a', 'b')?



У replace два перегруженных варианта — для одиночных символов и для строк. В java 8 быстрее работает метод для символов, в java 11 между ними почти нет разницы



Как удалить символы из строки?



В стандартной библиотеке нет метода remove. В java 11 для этой задачи подойдёт replace. В java 8 для критичных мест лучше взять StringUtils.remove из библиотеки Apache Commons Lang



Ниже — бенчмарки для разных джав и время в наносекундах. Результаты на разных железках могут отличаться!