У меня есть веревка
a.b.c.d
Я хочу посчитать появление "." идиоматическим способом, предпочтительно однострочным.
(Раньше я выражал это ограничение как «без цикла», на случай, если вам интересно, почему все пытаются ответить без использования цикла).
Не прочь от петель столько, сколько искать идиоматический однострочный.
Циклы были созданы для такой проблемы, напишите цикл в общем классе Utility, а затем вызовите свой недавно созданный один лайнер.
Аналогичный вопрос для строк: stackoverflow.com/questions/767759/…
Просто чтобы указать - я ценю поиск однострочных, это весело и (как истинное преимущество) часто легко запоминается, но я хотел бы указать, что отдельный метод и цикл лучше практически во всех отношениях. - читабельность и даже производительность. Большинство из приведенных ниже «элегантных» решений не будут работать очень хорошо, потому что они включают реформирование строк / копирование памяти, тогда как цикл, который просто просматривал строку и подсчитывал вхождения, был бы быстрым и простым. Не то чтобы производительность, как правило, должна быть фактором, но не смотрите на однострочную строку над циклом и предполагайте, что она будет работать лучше.
Возможный дубликат Найти вхождения символов в строке Java
@thSoft В будущем, пожалуйста, выбирайте вопросы / ответы с более высокими оценками в качестве повторяющейся цели.




Рано или поздно что-нибудь должен зацикливаться. Вам гораздо проще написать (очень простой) цикл, чем использовать что-то вроде split, которое намного мощнее, чем вам нужно.
Обязательно инкапсулируйте цикл в отдельный метод, например
public static int countOccurrences(String haystack, char needle)
{
int count = 0;
for (int i=0; i < haystack.length(); i++)
{
if (haystack.charAt(i) == needle)
{
count++;
}
}
return count;
}
Тогда вам не нужно иметь цикл в вашем основном коде - но цикл должен быть где-то там.
for (int i = 0, l = haystack.length (); i <l; i ++) будьте добры к своему стеку
(Я даже не уверен, откуда взялся бит "стек" комментария. Это не похоже на то, что ответ это является моим рекурсивным, что действительно неприятно для стека.)
не только это, но, возможно, это антиоптимизация, не глядя на то, что делает jit. Если вы сделали это, например, с массивом для цикла, вы могли бы ухудшить ситуацию.
Я думаю, что @Chris обеспокоен тем, что length() вызывается очень часто, что может повлиять на производительность при работе с большими строками. Предложение Криса сокращает доступ к length() до одного звонка.
@sulai: ИМО, опасения Криса безосновательны перед JIT-оптимизацией банальный. Есть ли причина, по которой этот комментарий привлек ваше внимание сейчас, более трех лет спустя? Просто интересно.
Вероятно, @sulai просто натолкнулся на вопрос, как и я (задаваясь вопросом, есть ли в Java для этого встроенный метод), и не заметил даты. Однако мне любопытно, как перемещение вызова length() за пределы цикла может повысить производительность хуже, как упомянул @ShuggyCoUk в нескольких комментариях.
Я согласен, что что-то должно зацикливаться, но это более кратко: for (int i = 0; (i = haystack.indexOf(needle, i)) >= 0; i++) { count++; }, конечно, можно критиковать за то, что он немного загадочен.
@njlarsson: Значит, у вас есть петля внутри цикла, но это не так очевидно. И да, я бы сказал, что это намного труднее читать.
@JonSkeet Полагаю, вы правы. Я думал, что «резко сокращает количество вызовов функций, если стрелка встречается редко», но я полагаю, что charAt будет встроен, если это критический код.
хороший needle по аналогии с haystack;)
(Извините за комментарий к старому сообщению) Как хорошая привычка, я бы порекомендовал реализацию @Chris в комментарии выше, которая переводит вызов length() на этап инициализации. Помимо «меньшего количества вызовов функций», он также избегает нетривиальные бесконечные циклы.
@SunnyPun: я бы сделал это в случаях, когда а) вычисление нетривиально - в этом случае я бы ожидал, что оно будет встроенным; б) есть шанс изменить повторяемую вещь. В этом случае, поскольку строки неизменяемы и мы не меняем значение haystack, я бы использовал эту версию.
вот решение без цикла:
public static int countOccurrences(String haystack, char needle, int i){
return ((i=haystack.indexOf(needle, i)) == -1)?0:1+countOccurrences(haystack, needle, i+1);}
System.out.println("num of dots is "+countOccurrences("a.b.c.d",'.',0));
ну есть петля, но это невидимый :-)
- Йонатан
Если ваша строка не слишком длинная, вы получите OutOfMemoryError.
Проблема кажется достаточно надуманной, чтобы быть домашним заданием, и если да, то эта рекурсия, вероятно, и есть ответ, который вас просят найти.
Это использует indexOf, который будет зацикливаться ... но хорошая идея. Публикация действительно "просто рекурсивного" решения за минуту ...
Если в нем больше вхождений, чем доступных слотов стека, у вас будет исключение переполнения стека;)
Петля не опасна. Рекурсия неконтролируемой глубины действительно опасна.
String s = "a.b.c.d";
int charCount = s.length() - s.replaceAll("\\.", "").length();
ReplaceAll (".") Заменит все символы.
Решение PhiLho использует ReplaceAll ("[^.]", ""), Который не нужно экранировать, поскольку [.] Представляет собой символ "точка", а не "любой символ".
Мне нравится этот. Конечно, есть еще петля, которая должна быть.
Обратите внимание, что вам нужно разделить это число, если вы хотите искать подстроки длиной> 1
У меня была идея, похожая на Младена, но наоборот ...
String s = "a.b.c.d";
int charCount = s.replaceAll("[^.]", "").length();
println(charCount);
Правильный. ReplaceAll (".") Заменит любой символ, а не только точку. ReplaceAll ("\\.") Сработало бы. Ваше решение более простое.
jjnguy на самом деле сначала предложил replaceAll ("[^.]"), увидев мое решение "a.b.c.d" .split ("\\."). length-1. Но после пяти ударов я удалил свой ответ (и его комментарий).
«... теперь у вас две проблемы» (обязательно). В любом случае, готов поспорить, что в replaceAll() и length() выполняются десятки циклов. Ну а если не видно, значит не существует; о)
replaceAll использует регулярное выражение, и он огромен для вычислений. Лучше простой цикл ...
я не думаю, что использовать регулярное выражение и создавать новую строку для подсчета. Я бы просто создал статический метод, который циклически повторяет каждый символ в строке для подсчета числа.
@mingfai: действительно, но исходный вопрос заключается в том, чтобы сделать однострочник и даже без цикла (вы можете сделать цикл в одной строке, но это будет некрасиво!). Ставьте под вопрос вопрос, а не ответ ... :-)
Мне нравится этот ответ, потому что он краток и прямолинеен.
Я не могу поверить, что ответ с регулярным выражением имеет 37 голосов. Вы все уволены!
Хорошо, вдохновленный решением Йонатана, вот тот, который является рекурсивным чисто - единственные используемые библиотечные методы - это length() и charAt(), ни один из которых не выполняет никаких циклов:
public static int countOccurrences(String haystack, char needle)
{
return countOccurrences(haystack, needle, 0);
}
private static int countOccurrences(String haystack, char needle, int index)
{
if (index >= haystack.length())
{
return 0;
}
int contribution = haystack.charAt(index) == needle ? 1 : 0;
return contribution + countOccurrences(haystack, needle, index+1);
}
Считается ли рекурсия зацикливанием, зависит от того, какое точное определение вы используете, но, вероятно, оно будет максимально точным.
Я не знаю, выполняет ли большинство JVM в наши дни хвостовую рекурсию ... в противном случае вы, конечно, получите одноименное переполнение стека для достаточно длинных строк.
Нет, хвостовая рекурсия, вероятно, будет в Java 7, но пока еще не получила широкого распространения. Эту простую прямую хвостовую рекурсию можно преобразовать в цикл во время компиляции, но материал Java 7 фактически встроен в JVM для обработки цепочки с помощью различных методов.
У вас будет больше шансов получить хвостовую рекурсию, если ваш метод вернет вызов самому себе (включая параметр текущего итога), а не результат выполнения добавления.
Хотя методы могут скрыть это, нет способа подсчета без цикла (или рекурсии). Однако вы хотите использовать char [] по соображениям производительности.
public static int count( final String s, final char c ) {
final char[] chars = s.toCharArray();
int count = 0;
for(int i=0; i<chars.length; i++) {
if (chars[i] == c) {
count++;
}
}
return count;
}
Использование replaceAll (то есть RE) - не лучший вариант.
Я считаю это наиболее элегантным решением. Почему вы использовали toCharArray, а не charAt напрямую?
Цикл с помощью char, по крайней мере, раньше был медленнее. Может зависеть и от платформы. Единственный способ узнать это - измерить разницу.
Вдохновленная Джоном Скитом, версия без цикла, которая не взорвет ваш стек. Также полезная отправная точка, если вы хотите использовать структуру fork-join.
public static int countOccurrences(CharSequeunce haystack, char needle) {
return countOccurrences(haystack, needle, 0, haystack.length);
}
// Alternatively String.substring/subsequence use to be relatively efficient
// on most Java library implementations, but isn't any more [2013].
private static int countOccurrences(
CharSequence haystack, char needle, int start, int end
) {
if (start == end) {
return 0;
} else if (start+1 == end) {
return haystack.charAt(start) == needle ? 1 : 0;
} else {
int mid = (end+start)>>>1; // Watch for integer overflow...
return
countOccurrences(haystack, needle, start, mid) +
countOccurrences(haystack, needle, mid, end);
}
}
(Отказ от ответственности: не проверено, не скомпилировано, не имеет смысла.)
Возможно, лучший (однопоточный, без поддержки суррогатных пар) способ его написания:
public static int countOccurrences(String haystack, char needle) {
int count = 0;
for (char c : haystack.toCharArray()) {
if (c == needle) {
++count;
}
}
return count;
}
Где-то в коде что-то должно зацикливаться. Единственный способ обойти это - полностью развернуть цикл:
int numDots = 0;
if (s.charAt(0) == '.') {
numDots++;
}
if (s.charAt(1) == '.') {
numDots++;
}
if (s.charAt(2) == '.') {
numDots++;
}
... и т.д., но тогда вы делаете цикл вручную в редакторе исходного кода, а не на компьютере, который будет его запускать. Смотрите псевдокод:
create a project
position = 0
while (not end of string) {
write check for character at position "position" (see above)
}
write code to output variable "numDots"
compile program
hand in homework
do not think of the loop that your "if"s may have been optimized and compiled to
Вот немного другое решение для рекурсии стиля:
public static int countOccurrences(String haystack, char needle)
{
return countOccurrences(haystack, needle, 0);
}
private static int countOccurrences(String haystack, char needle, int accumulator)
{
if (haystack.length() == 0) return accumulator;
return countOccurrences(haystack.substring(1), needle, haystack.charAt(0) == needle ? accumulator + 1 : accumulator);
}
Более короткий пример:
String text = "a.b.c.d";
int count = text.split("\\.",-1).length-1;
Кажется, что у этого есть относительно большие накладные расходы, имейте в виду, что он может создавать много маленьких строк. Обычно это не имеет большого значения, но используйте его с осторожностью.
Мой идиоматический однострочник:
int count = StringUtils.countMatches("a.b.c.d", ".");
Зачем писать самому, когда он уже в общий язык?
Единственный пример Spring Framework для этого:
int occurance = StringUtils.countOccurrencesOf("a.b.c.d", ".");
Эквивалент Гуава: int count = CharMatcher.is('.').countIn("a.b.c.d"); ... Как ответил dogbane в повторяющемся вопросе.
Хотя я не буду отрицать это, это (а) требует сторонних библиотек и (б) дорого.
Это только работа с пружинной рамой, которую нужно импортировать.
если кому то нужно: grepcode.com/file/repo1.maven.org/maven2/commons-lang/…
В каждой компании, в которой я работал, было дорого иметь множество плохо написанных и плохо обслуживаемых классов «* Utils». Часть вашей работы - знать, что доступно в Apache Commons.
Для Maven / Gradle: mvnrepository.com/artifact/org.apache.commons/commons-lang3/ 3.0
У меня есть базовое java-решение, проверьте это: stackoverflow.com/questions/3763970/…
Попробуйте этот метод:
StringTokenizer stOR = new StringTokenizer(someExpression, "||");
int orCount = stOR.countTokens()-1;
Голосовать против меня. Он не возвращает допустимые результаты во всех случаях, например, если мы считаем «a» в строке «a, a, a, a, a», он возвращает 3 вместо 5.
Если вы используете платформу Spring, вы также можете использовать класс StringUtils. Метод будет «countOccurrencesOf».
Почему бы просто не разделить на символ, а затем получить длину результирующего массива. длина массива всегда будет равна числу экземпляров +1. Верно?
public static int countOccurrences(String container, String content){
int lastIndex, currIndex = 0, occurrences = 0;
while(true) {
lastIndex = container.indexOf(content, currIndex);
if (lastIndex == -1) {
break;
}
currIndex = lastIndex + content.length();
occurrences++;
}
return occurrences;
}
Как насчет этого. Он не использует регулярное выражение внизу, поэтому должен быть быстрее, чем некоторые другие решения, и не будет использовать цикл.
int count = line.length() - line.replace(".", "").length();
Самый простой способ. Умный. И работает на Android, где нет класса StringUtils
Это лучший ответ. Причина, по которой это лучший вариант, заключается в том, что вам не нужно импортировать другую библиотеку.
Это не обязательно быстрее, чем другие решения, такие как StringUtils.countMatches, потому что ему нужно выделить некоторую память для возвращаемой строки. По-прежнему хорошее решение, когда производительность не критична.
Очень практично, но чертовски уродливо. Я не рекомендую это, так как это приводит к путанице в коде.
Уродливый код можно свести к минимуму, сделав его методом в вашем собственном классе StringUtils. Тогда уродливый код находится ровно в одном месте, а везде хорошо читается.
Это должно пройти строку три раз; сначала он должен вычислить длину, затем он должен заменить символы для подсчета (что также включает создание новой строки), затем он должен снова вычислить длину. Интересно, что такого плохого в цикле (очевидно, это вопрос не для Андреаса, а для OP)
Просто хочу добавить еще кое-что для новичков. Если у кого-то строка длиннее, чем ".", В этом случае разделите счет на длину строки, чтобы получить правильное количество этой подстроки.
String.replace(String, String) не использует регулярные выражения? Разве . не является подстановочным знаком в регулярном выражении? Итак, почему бы при замене не создать пустую строку?
Нет, String.replace не использует регулярное выражение. docs.oracle.com/javase/8/docs/api/java/lang/…
Метод цикла на много быстрее, чем этот. Особенно, если вы хотите подсчитать char вместо String (поскольку нет метода String.replace (char, char)). В строке из 15 символов я получаю разницу в 6049 нс против 26 739 нс (в среднем за 100 циклов). Необработанные числа - огромная разница, но с точки зрения восприятия ... она складывается. Избегайте выделения памяти - используйте цикл!
String.replace (CharSequnce, CharSequence) действительно использует регулярное выражение (посмотрите этот исходный код OpenJDK: goo.gl/O9dQzg) Для замены 1 символа на 1 символ используйте String.replace (char, char) для повышения производительности. Он просто перебирает символы строки: goo.gl/2FbcWP
Еще одна интересная вариация этого метода - подсчет появления целой строки или символа: int count = (sourceString.length() - sourceString.replace(searchString, "").length())/searcString.length();
@Grodriguez, это неправильно, Java String не заканчивается нулем и не должен перебирать символы, чтобы определить его длину. Вместо этого он использует внутри себя массив символов. Array.length - это O (1).
Я не говорил, что строки Java завершаются NUL, и не говорил, что для вычисления длины нужен цикл. В любом случае фактическая реализация String зависит от реализации.
Разве это не должно быть: int count = (line.length () - line.replace (".", "") .Length ()) / ".". Length (); предполагая, что вы хотите параметризовать строку "."?
Что ж, этот ответ настолько смущающе прост, я бы даже не подумал об этом через тысячу лет ...
Это очень неправильно, вы выделяете память для подсчета при линейном сканировании.
Полный образец:
public class CharacterCounter
{
public static int countOccurrences(String find, String string)
{
int count = 0;
int indexOf = 0;
while (indexOf > -1)
{
indexOf = string.indexOf(find, indexOf + 1);
if (indexOf > -1)
count++;
}
return count;
}
}
Вызов:
int occurrences = CharacterCounter.countOccurrences("l", "Hello World.");
System.out.println(occurrences); // 3
неправильный код, он не работает, когда я пытаюсь int instances = CharacterCounter.countOccurrences ("1", "101"); System.out.println (вхождения); // 1
Я фиксирую исправление для кода, работающего с той же логикой
import java.util.Scanner;
class apples {
public static void main(String args[]) {
Scanner bucky = new Scanner(System.in);
String hello = bucky.nextLine();
int charCount = hello.length() - hello.replaceAll("e", "").length();
System.out.println(charCount);
}
}// COUNTS NUMBER OF "e" CHAR´s within any string input
Не уверен в эффективности этого, но это самый короткий код, который я мог бы написать без использования сторонних библиотек:
public static int numberOf(String target, String content)
{
return (content.split(target).length - 1);
}
Чтобы также подсчитать вхождения в конце строки, вам нужно будет вызвать split с аргументом отрицательного лимита, например: return (content.split(target, -1).length - 1);. По умолчанию вхождения в конце строки опускаются в массиве в результате split (). См. Доку
Мне не нравится идея выделения для этой цели новой строки. И поскольку строка уже имеет массив символов в задней части, где она хранит свое значение, String.charAt () практически бесплатна.
for(int i=0;i<s.length();num+=(s.charAt(i++)==delim?1:0))
справляется с задачей без дополнительных выделений, требующих сбора, в 1 строке или меньше, только с J2SE.
Отдать немного любви к этому, потому что это единственный, кто делает один проход по струне. Я ДЕЙСТВИТЕЛЬНО забочусь о производительности.
charAt выполняет итерацию по 16-битным кодовым точкам, а не по символам! char в Java не является символом. Итак, этот ответ подразумевает, что не должно быть символа Unicode с высоким суррогатом, равным кодовой точке delim. Я не уверен, что это правильно для точки, но в целом это может быть неверно.
Следующий исходный код даст вам количество вхождений данной строки в слово, введенное пользователем: -
import java.util.Scanner;
public class CountingOccurences {
public static void main(String[] args) {
Scanner inp= new Scanner(System.in);
String str;
char ch;
int count=0;
System.out.println("Enter the string:");
str=inp.nextLine();
while(str.length()>0)
{
ch=str.charAt(0);
int i=0;
while(str.charAt(i)==ch)
{
count =count+i;
i++;
}
str.substring(count);
System.out.println(ch);
System.out.println(count);
}
}
}
public static int countSubstring(String subStr, String str) {
int count = 0;
for (int i = 0; i < str.length(); i++) {
if (str.substring(i).startsWith(subStr)) {
count++;
}
}
return count;
}
Почему вы пытаетесь избежать петли? Я имею в виду, что вы не можете сосчитать точки «numberOf», не проверив каждый отдельный символ строки, и если вы вызовете любую функцию, она каким-то образом зациклится. То есть String.replace должен выполнить цикл, проверяющий, появляется ли строка, чтобы она могла заменить каждое отдельное вхождение.
Если вы пытаетесь уменьшить использование ресурсов, вы этого не сделаете, потому что вы создаете новую строку только для подсчета точек.
Теперь, если мы говорим о рекурсивном методе «введите код здесь», кто-то сказал, что он не сработает из-за OutOfMemmoryException, я думаю, он забыл StackOverflowException.
Итак, мой метод будет таким (я знаю, что он похож на другие, но для этой проблемы требуется цикл):
public static int numberOf(String str,int c) {
int res=0;
if (str==null)
return res;
for(int i=0;i<str.length();i++)
if (c==str.charAt(i))
res++;
return res;
}
String s = "a.b.c.d";
long result = s.chars().filter(ch -> ch == '.').count();
Проголосуйте + за нативное решение.
Мое "идиоматическое однострочное" решение:
int count = "a.b.c.d".length() - "a.b.c.d".replace(".", "").length();
Понятия не имею, почему принято решение, использующее StringUtils.
В этом посте есть более старое решение, подобное этому.
Потому что это решение действительно неэффективно
Это создает дополнительную строку только для подсчета. Понятия не имею, почему кто-то предпочел бы это StringUtils, если StringUtils - вариант. Если это не вариант, им следует просто создать простой цикл for в служебном классе.
int count = (line.length() - line.replace("str", "").length())/"str".length();
С java-8 вы также можете использовать потоки для достижения этого. Очевидно, что за кулисами есть итерация, но вам не нужно писать ее явно!
public static long countOccurences(String s, char c){
return s.chars().filter(ch -> ch == c).count();
}
countOccurences("a.b.c.d", '.'); //3
countOccurences("hello world", 'l'); //3
Тогда использование .codePoints() вместо .chars() будет поддерживать любое значение Unicode (включая те, которые требуют суррогатных пар).
А как насчет ниже рекурсивного алгоритма, который также является линейным временем.
import java.lang.*;
import java.util.*;
class longestSubstr{
public static void main(String[] args){
String s = "ABDEFGABEF";
int ans=calc(s);
System.out.println("Max nonrepeating seq= "+ans);
}
public static int calc(String s)
{//s.s
int n=s.length();
int max=1;
if (n==1)
return 1;
if (n==2)
{
if (s.charAt(0)==s.charAt(1)) return 1;
else return 2;
}
String s1=s;
String a=s.charAt(n-1)+"";
s1=s1.replace(a,"");
// System.out.println(s+" "+(n-2)+" "+s.substring(0,n-1));
max=Math.max(calc(s.substring(0,n-1)),(calc(s1)+1));
return max;
}
}
</i>
Я вижу, что используется много уловок и тому подобных. Я не против красивых трюков, но лично мне нравится просто вызывать методы имел в виду для выполнения работы, поэтому я создал еще один ответ.
Обратите внимание, что если производительность является какой-либо проблемой, используйте вместо этого Ответ Джона Скита. Этот вариант немного более обобщен и поэтому, на мой взгляд, немного более читабелен (и, конечно же, его можно использовать повторно для строк и шаблонов).
public static int countOccurances(char c, String input) {
return countOccurancesOfPattern(Pattern.quote(Character.toString(c)), input);
}
public static int countOccurances(String s, String input) {
return countOccurancesOfPattern(Pattern.quote(s), input);
}
public static int countOccurancesOfPattern(String pattern, String input) {
Matcher m = Pattern.compile(pattern).matcher(input);
int count = 0;
while (m.find()) {
count++;
}
return count;
}
public class OccurencesInString { public static void main(String[] args) { String str = "NARENDRA AMILINENI"; HashMap occur = new HashMap(); int count =0; String key = null; for(int i=0;i<str.length()-1;i++){ key = String.valueOf(str.charAt(i)); if (occur.containsKey(key)){ count = (Integer)occur.get(key); occur.put(key,++count); }else{ occur.put(key,1); } } System.out.println(occur); } }
Я вижу, что этот ответ усечен, поэтому, возможно, вам не нужны следующие предложения. Но на всякий случай: 1) Не вставляйте просто код. Поясните немного, расскажите, почему вы считаете это хорошим решением. 2) Отформатируйте свой код: stackoverflow.com/editing-help
Ответы, содержащие только код, автоматически помечаются как низкое качество и поэтому не приветствуются при stackoverflow. В будущем, пожалуйста, приукрасите свой ответ подробностями и объясните, почему это решение вопроса. Это помогает другим пользователям. Также - вы никогда не слышали о возврате каретки ??
Я попытался решить ваш вопрос с помощью оператора switch, но мне все еще нужен цикл for для анализа строки. не стесняйтесь комментировать, могу ли я улучшить код
public class CharacterCount {
public static void main(String args[])
{
String message = "hello how are you";
char[] array=message.toCharArray();
int a=0;
int b=0;
int c=0;
int d=0;
int e=0;
int f=0;
int g=0;
int h=0;
int i=0;
int space=0;
int j=0;
int k=0;
int l=0;
int m=0;
int n=0;
int o=0;
int p=0;
int q=0;
int r=0;
int s=0;
int t=0;
int u=0;
int v=0;
int w=0;
int x=0;
int y=0;
int z=0;
for(char element:array)
{
switch(element)
{
case 'a':
a++;
break;
case 'b':
b++;
break;
case 'c':c++;
break;
case 'd':d++;
break;
case 'e':e++;
break;
case 'f':f++;
break;
case 'g':g++;
break;
case 'h':
h++;
break;
case 'i':i++;
break;
case 'j':j++;
break;
case 'k':k++;
break;
case 'l':l++;
break;
case 'm':m++;
break;
case 'n':m++;
break;
case 'o':o++;
break;
case 'p':p++;
break;
case 'q':q++;
break;
case 'r':r++;
break;
case 's':s++;
break;
case 't':t++;
break;
case 'u':u++;
break;
case 'v':v++;
break;
case 'w':w++;
break;
case 'x':x++;
break;
case 'y':y++;
break;
case 'z':z++;
break;
case ' ':space++;
break;
default :break;
}
}
System.out.println("A "+a+" B "+ b +" C "+c+" D "+d+" E "+e+" F "+f+" G "+g+" H "+h);
System.out.println("I "+i+" J "+j+" K "+k+" L "+l+" M "+m+" N "+n+" O "+o+" P "+p);
System.out.println("Q "+q+" R "+r+" S "+s+" T "+t+" U "+u+" V "+v+" W "+w+" X "+x+" Y "+y+" Z "+z);
System.out.println("SPACE "+space);
}
}
Это как можно дальше от однострочника. Ужасный.
Попробуйте этот код:
package com.java.test;
import java.util.HashMap;
import java.util.Map;
public class TestCuntstring {
public static void main(String[] args) {
String name = "Bissssmmayaa";
char[] ar = new char[name.length()];
for (int i = 0; i < name.length(); i++) {
ar[i] = name.charAt(i);
}
Map<Character, String> map=new HashMap<Character, String>();
for (int i = 0; i < ar.length; i++) {
int count=0;
for (int j = 0; j < ar.length; j++) {
if (ar[i]==ar[j]){
count++;
}
}
map.put(ar[i], count+" no of times");
}
System.out.println(map);
}
}
Ну, с довольно похожей задачей наткнулся на эту тему. Я не видел никаких ограничений языка программирования, и поскольку groovy работает на java vm: Вот как я смог решить свою проблему с помощью Groovy.
"a.b.c.".count(".")
Готово.
Обобщите другой ответ и то, что я знаю, все способы сделать это с помощью однострочника:
String testString = "a.b.c.d";
1) Использование Apache Commons
int apache = StringUtils.countMatches(testString, ".");
System.out.println("apache = " + apache);
2) Использование Spring Framework's
int spring = org.springframework.util.StringUtils.countOccurrencesOf(testString, ".");
System.out.println("spring = " + spring);
3) Использование заменять
int replace = testString.length() - testString.replace(".", "").length();
System.out.println("replace = " + replace);
4) Использование заменить все (случай 1)
int replaceAll = testString.replaceAll("[^.]", "").length();
System.out.println("replaceAll = " + replaceAll);
5) Использование заменить все (случай 2)
int replaceAllCase2 = testString.length() - testString.replaceAll("\\.", "").length();
System.out.println("replaceAll (second case) = " + replaceAllCase2);
6) Использование расколоть
int split = testString.split("\\.",-1).length-1;
System.out.println("split = " + split);
7) Использование Java8 (случай 1)
long java8 = testString.chars().filter(ch -> ch =='.').count();
System.out.println("java8 = " + java8);
8) Использование Java8 (случай 2) может быть лучше для юникода, чем случай 1
long java8Case2 = testString.codePoints().filter(ch -> ch =='.').count();
System.out.println("java8 (second case) = " + java8Case2);
9) Использование StringTokenizer
int stringTokenizer = new StringTokenizer(" " +testString + " ", ".").countTokens()-1;
System.out.println("stringTokenizer = " + stringTokenizer);
Из комментария: Будьте осторожны с StringTokenizer, для abcd он будет работать, но для a ... bc ... d или ... abcd или a .... b ...... c ..... d. .. или т.д. не получится. Это просто будет считаться. между персонажами только один раз
Больше информации в github
Тест производительности (с использованием JMH, mode = AverageTime, оценка 0.010 лучше, чем 0.351):
Benchmark Mode Cnt Score Error Units
1. countMatches avgt 5 0.010 ± 0.001 us/op
2. countOccurrencesOf avgt 5 0.010 ± 0.001 us/op
3. stringTokenizer avgt 5 0.028 ± 0.002 us/op
4. java8_1 avgt 5 0.077 ± 0.005 us/op
5. java8_2 avgt 5 0.078 ± 0.003 us/op
6. split avgt 5 0.137 ± 0.009 us/op
7. replaceAll_2 avgt 5 0.302 ± 0.047 us/op
8. replace avgt 5 0.303 ± 0.034 us/op
9. replaceAll_1 avgt 5 0.351 ± 0.045 us/op
Напечатанные строки не совпадают с приведенными выше, и порядок сначала самый быстрый, что, по крайней мере, усложняет поиск. В остальном хороший ответ!
случай 2, обобщенный для кодовых точек, которым требуется более одной кодовой единицы UTF-16: "1?2?3 has 2".codePoints().filter((c) -> c == "?".codePointAt(0)).count()
Вы можете использовать функцию split() всего в одной строке кода
int noOccurence=string.split("#",-1).length-1;
Split действительно создает массив строк, на что уходит много времени.
Вы правы, это проблема правда. С другой стороны, он позволяет избежать использования сторонней библиотеки в вашем проекте (если это еще не сделано). Это зависит от того, что вы хотите сделать, и от ожидаемой производительности.
Это решение НЕ будет включать завершающие пустые совпадения, потому что аргумент limit установлен в ноль в этом перегруженном вызове метода разделения. Пример: "1##2#3#####".split("#") даст только массив размера 4 ([0:"1";1:""; 2:"2"; 3:"3"]) вместо размера 9 ([0:"1"; 1:""; 2:"2"; 3:"3"; 4:""; 5:""; 6:""; 7:""; 8:""]).
Если вы хотите посчитать «нет». того же символа в строке «SELENIUM» или вы хотите напечатать уникальные символы строки «SELENIUM».
public class Count_Characters_In_String{
public static void main(String []args){
String s = "SELENIUM";
System.out.println(s);
int counter;
String g = "";
for( int i=0; i<s.length(); i++ ) {
if (g.indexOf(s.charAt(i)) == - 1){
g=g+s.charAt(i);
}
}
System.out.println(g + " ");
for( int i=0; i<g.length(); i++ ) {
System.out.print(",");
System.out.print(s.charAt(i)+ " : ");
counter=0;
for( int j=0; j<s.length(); j++ ) {
if ( g.charAt(i) == s.charAt(j) ) {
counter=counter+1;
}
}
System.out.print(counter);
}
}
}
/******************** ВЫХОД **********************/
СЕЛЕН
СЕЛНИУМ
S: 1, E: 2, L: 1, E: 1, N: 1, I: 1, U: 1
Самый простой способ получить ответ:
public static void main(String[] args) {
String string = "a.b.c.d";
String []splitArray = string.split("\\.",-1);
System.out.println("No of . chars is : " + (splitArray.length-1));
}
Этот фрагмент кода не возвращает правильное количество точек для заданного ввода «a.b.c.»
@dekaru Не могли бы вы вставить свое жало в комментарий, чтобы мы могли посмотреть.
Также можно использовать сокращение в Java 8 для решения этой проблемы:
int res = "abdsd3$asda$asasdd$sadas".chars().reduce(0, (a, c) -> a + (c == '$' ? 1 : 0));
System.out.println(res);
Выход:
3
Использование Коллекции Eclipse
int count = Strings.asChars("a.b.c.d").count(c -> c == '.');
Если у вас есть более одного символа для подсчета, вы можете использовать CharBag следующим образом:
CharBag bag = Strings.asChars("a.b.c.d").toBag();
int count = bag.occurrencesOf('.');
Примечание: я являюсь приверженцем коллекций Eclipse.
String[] parts = text.split(".");
int occurances = parts.length - 1;
" It's a great day at O.S.G. Dallas! "
-- Famous Last Words
Что ж, это случай знания вашей Java, особенно вашего базового понимания классов коллекций, уже доступных в Java. Если вы просмотрите всю публикацию здесь, есть почти все, кроме объяснения Стивена Хокинга о Происхождении Вселенной, мягкой обложки Дарвина об эволюции и выбора актерского состава Джина Родденберри из Звездного пути о том, почему они пошли с Уильямом Шатнером, не дожидаясь, как это сделать это быстро и легко ...
... мне нужно больше говорить?
Можете ли вы добавить к этому объяснение вместо того, чтобы просто размещать код?
Это создает массив parts, который необходимо выделить, а затем собрать мусор. Совершенно ненужные накладные расходы. Попробуйте сделать это в плотном цикле.
Кроме того, не следует ли его разбивать ("\\.") Для разбивки по точкам?
Кроме того, если строка "foo." результат будет таким же, как если бы строка была «полосой»
public static void getCharacter(String str){
int count[]= new int[256];
for(int i=0;i<str.length(); i++){
count[str.charAt(i)]++;
}
System.out.println("The ascii values are:"+ Arrays.toString(count));
//Now display wht character is repeated how many times
for (int i = 0; i < count.length; i++) {
if (count[i] > 0)
System.out.println("Number of " + (char) i + ": " + count[i]);
}
}
}
Кусок кода - не лучший ответ. Может быть, попытайтесь расширить это рассуждениями, объяснениями, подводными камнями и т. д.
Java не использует ASCII; char - это кодовая единица UTF-16. Диапазон значений: 0..Character.MAX_VALUE. Ваш алгоритм работает, если целью является подсчет случаев использования кодовых единиц UTF-16.
Использование Java 8 и HashMap без какой-либо библиотеки для подсчета всех разных символов:
private static void countChars(String string) {
HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
string.chars().forEach(letter -> hm.put(letter, (hm.containsKey(letter) ? hm.get(letter) : 0) + 1));
hm.forEach((c, i) -> System.out.println(((char)c.intValue()) + ":" + i));
}
используйте лямбда-функцию, которая удаляет все символы для подсчета
счетчик - это разница между длиной до и после
String s = "a.b.c.d";
int count = s.length() - deleteChars.apply( s, "." ).length(); // 3
если вам нужно подсчитать появление более чем одного символа, это можно сделать одним махом:
например. для bc и .:
int count = s.length() - deleteChars.apply( s, "bc." ).length(); // 5
Гораздо более простым решением было бы просто разделить строку на основе символа, с которым вы ее сопоставляете.
Например,
int getOccurences(String characters, String string) {
String[] words = string.split(characters);
return words.length - 1;
}
Это вернет 4 в случае:
getOccurences("o", "something about a quick brown fox");
Проблема здесь в том, что нужно выделить массив, что ужасно медленно.
Это то, что я использую для подсчета вхождений строки.
Надеюсь, кто-то сочтет это полезным.
private long countOccurrences(String occurrences, char findChar){
return occurrences.chars().filter( x -> {
return x == findChar;
}).count();
}
однострочное лямбда
без необходимости во внешней библиотеке.
Создает карту с количеством каждого символа:
Map<Character,Long> counts = "a.b.c.d".codePoints().boxed().collect(
groupingBy( t -> (char)(int)t, counting() ) );
получает: {a=1, b=1, c=1, d=1, .=3}
количество определенного символа, например. '.' отдан: counts.get( '.' )
(Я также пишу лямбда-решение из болезненного любопытства, чтобы узнать, насколько медленным является мое решение, желательно от человека с 10-строчным решением.)
Домашнее задание? Потому что в противном случае я не вижу необходимости избегать цикла.