У меня есть строка
a.b.c.d
Я хочу подсчитать вхождения '.' идиоматическим способом, предпочтительно однострочным.
(Раньше я выражал это ограничение как "без цикла", если вам интересно, почему все пытаются ответить, не используя цикл).
Мой "идиоматический однострочный" для этого:
int count = StringUtils.countMatches("a.b.c.d", ".");
Зачем писать его самостоятельно, когда он уже находится в commons lang?
Spring Framework oneliner для этого:
int occurance = StringUtils.countOccurrencesOf("a.b.c.d", ".");
int count = CharMatcher.is('.').countIn("abcd");
... Как ответил Dogbane в повторяющемся вопросе.
Как насчет этого. Он не использует regexp внизу, поэтому должен быть быстрее, чем некоторые другие решения, и не будет использовать цикл.
int count = line.length() - line.replace(".", "").length();
Подведите итог другому ответу, и я знаю все способы сделать это с помощью однострочного интерфейса:
String testString = "a.b.c.d";
1) Использование Apache Commons
int apache = StringUtils.countMatches(testString, ".");
System.out.println("apache = " + apache);
2) Используя Spring Framework
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) Используя replaceAll (случай 1)
int replaceAll = testString.replaceAll("[^.]", "").length();
System.out.println("replaceAll = " + replaceAll);
5) Используя replaceAll (случай 2)
int replaceAllCase2 = testString.length() - testString.replaceAll("\\.", "").length();
System.out.println("replaceAll (second case) = " + replaceAllCase2);
6) Используя split
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) может быть лучше для unicode, чем случай 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 он будет работать, но для... bc... d или... abcd или a... b...... c..... d... или т.д. это не сработает. Он просто рассчитывает. между символами только один раз
Дополнительная информация в github
Perfomance test (используя 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
Рано или поздно что-то должно зацикливаться. Для вас гораздо проще написать (очень простой) цикл, чем использовать что-то вроде 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;
}
Тогда вам не нужно иметь цикл в вашем основном коде, но цикл должен быть где-то там.
У меня была идея, похожая на Младена, но наоборот...
String s = "a.b.c.d";
int charCount = s.replaceAll("[^.]", "").length();
println(charCount);
String s = "a.b.c.d";
int charCount = s.length() - s.replaceAll("\\.", "").length();
ReplaceAll ( "." ) заменит все символы.
Решение PhiLho использует ReplaceAll ( "[^.]", "" ), который не нужно экранировать, поскольку [.] представляет символ "точка" ', а не "любой символ".
Мое решение 'iiomatic one-liner':
int count = "a.b.c.d".length() - "a.b.c.d".replace(".", "").length();
Не знаю, почему принимается решение, использующее StringUtils.
String s = "a.b.c.d";
long result = s.chars().filter(ch -> ch == '.').count();
Более короткий пример
String text = "a.b.c.d";
int count = text.split("\\.",-1).length-1;
здесь есть решение без цикла:
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));
ну, есть цикл, но он невидим: -)
- Йонатан
Мне не нравится идея выделения новой строки для этой цели. И поскольку в строке уже есть массив char, где он хранит это значение, String.charAt() практически свободен.
for(int i=0;i<s.length();num+=(s.charAt(i++)==delim?1:0))
делает трюк без дополнительных ассигнований, которые нуждаются в коллекции, в 1 строке или меньше, только с J2SE.
Хорошо, вдохновленный решением Yonatan, здесь, который является чисто рекурсивным - единственными используемыми библиотечными методами являются 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 хвостовую рекурсию в эти дни... если нет, вы, конечно, получите переполнение одноименного стека для подходящих длинных строк.
Вдохновленный Джон Скит, не-петлевая версия, которая не ударит ваш стек. Также полезной отправной точкой, если вы хотите использовать инфраструктуру 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;
}
С 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 (включая те, которые требуют суррогатных пар)
Не уверен в эффективности этого, но это самый короткий код, который я мог бы написать без привлечения сторонних библиотек:
public static int numberOf(String target, String content)
{
return (content.split(target).length - 1);
}
return (content.split(target, -1).length - 1);
, По умолчанию вхождения в конце строки опускаются в массиве, являющемся результатом split (). Посмотри Доку
Полный образец:
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
Самый простой способ получить ответ:
public static void main(String[] args) {
String string = "a.b.c.d";
String []splitArray = string.split("\\.");
System.out.println("No of . chars is : " + splitArray.length-1);
}
Также можно использовать сокращение в Java 8 для решения этой проблемы:
int res = "abdsd3$asda$asasdd$sadas".chars().reduce(0, (a, c) -> a + (c == '$' ? 1 : 0));
System.out.println(res);
Вывод:
3
Если вы используете фреймворк Spring, вы также можете использовать класс "StringUtils". Этот метод будет "countOccurrencesOf".
Вы можете использовать функцию split()
только в одном строковом коде
int noOccurence=string.split("#").length-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
String[] parts = text.split(".");
int occurances = parts.length - 1;
" It a great day at O.S.G. Dallas! "
-- Famous Last Words
Ну, это случай знания вашей Java, особенно ваше базовое базовое понимание классов коллекции, уже доступных на Java. Если вы посмотрите на всю публикацию здесь, есть почти все, что не объясняет объяснение Стивена Хокинга "Происхождение Вселенной", книга Дарвина в "Эволюции" и "Джин Родденберри Звездный путь" отдали предпочтение тому, почему они поехали с Уильямом Шатнером, это быстро и легко...
... нужно больше сказать?
parts
, который должен быть выделен, а затем собран мусор. Совершенно ненужные накладные расходы. Попробуйте сделать это в тесной петле.
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;
}
В то время как методы могут скрыть это, нет возможности считать без цикла (или рекурсии). Однако вы хотите использовать 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) не похоже на лучший способ.
Использование Коллекции Eclipse
int count = CharAdapter.adapt("a.b.c.d").count(c -> c == '.');
Если у вас есть более одного символа для подсчета, вы можете использовать CharBag
следующим образом:
CharBag bag = CharAdapter.adapt("a.b.c.d").toBag();
int count = bag.occurrencesOf('.');
Примечание. Я являюсь коммиттером для коллекций Eclipse.
int count = (line.length() - line.replace("str", "").length())/"str".length();
Следующий исходный код даст вам no.of вхождения данной строки в слово, введенное пользователем: -
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);
}
}
}
Почему бы просто не разбить на символ, а затем получить длину результирующего массива. длина массива всегда будет числом экземпляров + 1. Правильно?
Вот немного другое решение для рекурсии стиля:
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);
}
Где-то в коде что-то должно зацикливаться. Единственный путь вокруг этого - полное разворачивание цикла:
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
Ну, с такой же задачей я наткнулся на эту тему. Я не видел ограничений языка программирования, так как groovy работает на java vm: Вот как я смог решить мою проблему с помощью Groovy.
"a.b.c.".count(".")
сделанный.
Я вижу много трюков и их использование. Теперь я не против красивых трюков, но лично мне нравится просто называть методы, предназначенные для выполнения этой работы, поэтому я создал еще один ответ.
Обратите внимание, что если производительность представляет собой какую-либо проблему, вместо этого используйте Jon Skeet. Это немного более обобщенно и, следовательно, немного читаемо, на мой взгляд (и, конечно, многократно используется для строк и паттернов).
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;
}
Почему вы пытаетесь избежать цикла? Я имею в виду, что вы не можете считать точки "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;
}
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;
}
Попробуйте этот метод:
StringTokenizer stOR = new StringTokenizer(someExpression, "||");
int orCount = stOR.countTokens()-1;
Если вы хотите считать нет. одного символа в строке "SELENIUM" или вы хотите напечатать уникальные символы строки "SELENIUM".
открытый класс 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);
}
}
}
/******************** ВЫХОД **********************/
СЕЛЕН
SELNIUM
S: 1, E: 2, L: 1, E: 1, N: 1, I: 1, U: 1
Попробуйте этот код:
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);
}
}
Как насчет ниже рекурсивного алгоритма. Это также линейное время.
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 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]);
}
}
}
char
- это кодовая единица UTF-16. Диапазон составляет 0..Character.MAX_VALUE. Ваш алгоритм работает, если целью является подсчет вхождений кодовых единиц UTF-16.
Я попытался выработать ваш вопрос с помощью оператора 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);
}
}
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); } }