Программирование

Подсчёт символов в строке Java: идиоматичные методы

Эффективные способы подсчёта вхождений символа в строку Java без циклов. Использование String.replace(), Java 8 Stream API и внешних библиотек.

7 ответов 1 просмотр

Как подсчитать количество вхождений символа в строку в Java идиоматичным способом, предпочтительно в одну строку без циклов?

У меня есть строка:

a.b.c.d

Хочу посчитать количество символов ‘.’.

Подсчёт количества вхождений символа в строку Java можно выполнить несколькими идиоматичными способами без явных циклов. Самые эффективные однострочные решения используют String.replace() или Java 8 Stream API, которые позволяют получить результат в одной строке кода.


Содержание


Идиоматичные способы подсчёта символов в строке Java

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

Самый простой и эффективный способ подсчёта символов в строке - использование метода replace(), который заменяет все вхождения одного символа на другой. Вычитая длину исходной строки из длины строки с удалёнными символами, мы получаем количество вхождений.

Другой современный подход использует Java 8 Stream API, где метод chars() преобразует строку в IntStream символов, после чего можно отфильтровать нужные символы и посчитать их количество с помощью count(). Этот подход особенно хорош при работе с Unicode-символами и предоставляет функциональный стиль программирования.


Использование String.replace() для подсчёта вхождений

Классический метод подсчёта вхождений символа в строку с использованием replace() является одним из самых производительных и простых в реализации. Суть метода заключается в том, чтобы заменить все целевые символы на пустую строку и сравнить длину полученной строки с исходной.

java
String text = "a.b.c.d";
int count = text.length() - text.replace(".", "").length();
// Результат: 3

Этот метод работает следующим образом:

  1. text.replace(".", "") удаляет все точки из строки, получая “abcd”
  2. text.length() даёт 7 (длина исходной строки)
  3. text.replace(".", "").length() даёт 4 (длина строки без точек)
  4. Разница составляет 7 - 4 = 3 точки

Преимущества этого подхода:

  • Высокая производительность - метод replace() оптимизирован в JVM
  • Простота понимания - логика интуитивно ясна
  • Отсутствие внешних зависимостей - использует только стандартную библиотеку Java
  • Эффективная работа с короткими строками - для большинства практических случаев это оптимальный выбор

Однако важно учитывать, что этот метод создаёт временные строковые объекты при каждом вызове, что может быть неэффективным при обработке очень больших строк в циклах.


Java 8 Stream API для подсчёта символов

Java 8 Stream API предоставляет современный функциональный подход к подсчёту символов в строке. Этот метод особенно хорош при работе с Unicode-символами и предоставляет декларативный стиль программирования.

java
String text = "a.b.c.d";
long count = text.chars().filter(ch -> ch == '.').count();
// Результат: 3

// Для Unicode-символов
long unicodeCount = text.codePoints().filter(cp -> cp == '.').count();
// Результат: 3

Этот подход работает следующим образом:

  1. text.chars() преобразует строку в IntStream кодов символов
  2. .filter(ch -> ch == '.') отфильтровывает только символы, равные точке
  3. .count() подсчитывает количество отфильтрованных элементов

Преимущества Stream API:

  • Читаемость - код легко понимается как декларативное описание операции
  • Поддержка Unicode - метод codePoints() корректно работает с многобайтовыми символами
  • Функциональный стиль - соответствует современным практикам функционального программирования
  • Гибкость - легко расширяется для более сложных операций с символами

Дополнительный метод с использованием reduce():

java
int count = text.chars().reduce(0, (a, c) -> a + (c == '.' ? 1 : 0));
// Результат: 3

Этот метод накапливает счётчик, прибавляя 1 каждый раз, когда встречается целевой символ.


Использование внешних библиотек

При работе с большими проектами часто используются внешние библиотеки, предоставляющие готовые утилиты для подсчёта символов. Apache Commons Lang и Spring Framework предлагают удобные методы для этой задачи.

Apache Commons Lang

java
import org.apache.commons.lang3.StringUtils;

String text = "a.b.c.d";
int count = StringUtils.countMatches(text, ".");
// Результат: 3

Spring Framework

java
import org.springframework.util.StringUtils;

String text = "a.b.c.d";
int count = StringUtils.countOccurrencesOf(text, ".");
// Результат: 3

Преимущества использования библиотек:

  • Готовые решения - не нужно реализовывать стандартную функциональность
  • Тестированность - методы тщательно протестированы и отлажены
  • Дополнительная функциональность - библиотеки предлагают множество полезных методов
  • Совместимость - работают в различных контекстах проектов

Однако стоит учитывать, что использование внешних библиотек добавляет зависимости в проект, что может быть нежелательным в некоторых случаях.


Сравнение производительности различных методов

Производительность различных методов подсчёта символов может значительно различаться в зависимости от размера строки и конкретной реализации. Согласно тестам, проведённым на Stack Overflow, можно выделить следующие результаты:

java
String testString = "a.b.c.d";

// 1. Apache Commons StringUtils.countMatches
long apache = StringUtils.countMatches(testString, "."); // ~0.010 μs

// 2. Spring Framework StringUtils.countOccurrencesOf 
long spring = StringUtils.countOccurrencesOf(testString, "."); // ~0.010 μs

// 3. StringTokenizer
long stringTokenizer = new StringTokenizer(" " + testString + " ", ".").countTokens()-1; // ~0.028 μs

// 4. Java 8 Stream API
long java8 = testString.chars().filter(ch -> ch == '.').count(); // ~0.077 μs

// 5. String.split
long split = testString.split(".", -1).length-1; // ~0.137 μs

// 6. String.replaceAll (вариант 2)
long replaceAll2 = testString.length() - testString.replaceAll(".", "").length(); // ~0.302 μs

// 7. String.replace
long replace = testString.length() - testString.replace(".", "").length(); // ~0.303 μs

// 8. String.replaceAll (вариант 1)
long replaceAll1 = testString.replaceAll("[^.]", "").length(); // ~0.351 μs

Анализ результатов:

  • Самые быстрые - методы из Apache Commons и Spring Framework (~0.010 μs)
  • Оптимальные для чистого Java - String.replace() (~0.303 μs)
  • Современные подходы - Java 8 Stream API (~0.077 μs)
  • Менее эффективные - методы с replaceAll и split (0.137-0.351 μs)

Рекомендации по выбору метода:

  • Для высокопроизводительных систем - использовать готовые методы из библиотек
  • Для стандартных приложений - String.replace() или Java 8 Stream API
  • Для работы с Unicode - codePoints() из Stream API
  • Для минимизации зависимостей - String.replace()

Источники

  1. Stack Overflow - Count character occurrences in a string — Множество методов подсчёта символов в строке Java с примерами кода: https://stackoverflow.com/questions/275944/how-do-i-count-the-number-of-occurrences-of-a-char-in-a-string
  2. Scaler Topics - Occurrence of Character in String in Java — Обзор идиоматичных способов подсчёта символов в Java 8: https://www.scaler.com/topics/occurrence-of-character-in-string-in-java/
  3. Apache Commons Lang Documentation — Официальная документация по StringUtils.countMatches: https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html#countMatches(java.lang.CharSequence, java.lang.CharSequence)
  4. Spring Framework Documentation — Документация по StringUtils.countOccurrencesOf: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/util/StringUtils.html#countOccurrencesOf-java.lang.String-java.lang.String-

Заключение

Для подсчёта количества вхождений символа в строку Java существует несколько идиоматичных способов без явных циклов. Наиболее производительным методом является использование String.replace(), который позволяет получить результат в одной строке кода. Для функционального подхода отлично подходит Java 8 Stream API с методами chars() или codePoints(). В проектах, использующих внешние библиотеки, можно применять готовые методы из Apache Commons Lang или Spring Framework.

Выбор конкретного метода зависит от требований производительности, необходимости поддержки Unicode и наличия зависимостей в проекте. Для большинства практических случаев оптимальным решением остаётся использование String.replace() или Stream API, которые обеспечивают хороший баланс между производительностью и читаемостью кода.

A

Для подсчёта количества вхождений символа в строку можно использовать метод String.replace() для замены всех вхождений символа на пустую строку, затем вычислить разницу длин: int count = originalString.length() - originalString.replace(String.valueOf(char), “”).length();

C

Самый простой способ подсчитать количество вхождений символа в строку - использовать String.replace() для замены всех вхождений на пустую строку и сравнить длины: int count = originalString.length() - originalString.replace(String.valueOf(char), “”).length();

S

Для подсчёта количества вхождений символа в строку в Java можно использовать метод String.replace() для замены всех вхождений символа на пустую строку, затем вычислить разницу длин: int count = originalString.length() - originalString.replace(String.valueOf(char), “”).length();

J

Для подсчёта количества вхождений символа в строку в Java можно использовать метод String.replace() для замены всех вхождений символа на пустую строку, затем вычислить разницу длин: int count = originalString.length() - originalString.replace(String.valueOf(char), “”).length();

T

Для подсчёта количества вхождений символа в строку в Java можно использовать метод String.replace() для замены всех вхождений символа на пустую строку, затем вычислить разницу длин: int count = originalString.length() - originalString.replace(String.valueOf(char), “”).length();

GeeksforGeeks / Документация

В Java можно подсчитать количество вхождений символа в строку с помощью метода String.replace(). Создайте новую строку, заменив все вхождения символа на пустую строку, затем вычтите длину новой строки из длины исходной: int count = originalString.length() - originalString.replace(String.valueOf(char), “”).length();

Авторы
A
Пользователь
C
Разработчик
S
Разработчик
J
Разработчик
T
Инструктор
Источники
Stack Overflow / Платформа Q&A
Платформа Q&A
GeeksforGeeks / Документация
Документация
Документация
Проверено модерацией