Question Java: Comment compter le nombre d'occurrences d'un caractère dans une chaîne?


J'ai la ficelle

a.b.c.d

Je veux compter les occurrences de '.' d'une manière idiomatique, de préférence un one-liner.

(Auparavant, j'avais exprimé cette contrainte comme "sans boucle", au cas où vous vous demandez pourquoi tout le monde essaie de répondre sans utiliser de boucle).


438
2017-11-09 14:07


origine


Réponses:


Mon «one-liner idiomatique» pour ceci est:

int count = StringUtils.countMatches("a.b.c.d", ".");

Pourquoi l'écrire vous-même quand il est déjà dans commons lang?

L'onliner de Spring Framework pour cela est:

int occurance = StringUtils.countOccurrencesOf("a.b.c.d", ".");

616
2017-11-29 22:23



Que dis-tu de ça. Il n'utilise pas l'expression rationnelle en dessous, elle devrait donc être plus rapide que certaines des autres solutions et ne pas utiliser de boucle.

int count = line.length() - line.replace(".", "").length();

873
2018-01-18 13:17



Résumez autre réponse et ce que je connais tous les moyens de le faire en utilisant un one-liner:

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

1) Utilisation Apache Commons

int apache = StringUtils.countMatches(testString, ".");
System.out.println("apache = " + apache);

2) Utilisation Spring Framework de

int spring = org.springframework.util.StringUtils.countOccurrencesOf(testString, ".");
System.out.println("spring = " + spring);

3) Utilisation remplacer

int replace = testString.length() - testString.replace(".", "").length();
System.out.println("replace = " + replace);

4) Utilisation remplace tout (cas 1)

int replaceAll = testString.replaceAll("[^.]", "").length();
System.out.println("replaceAll = " + replaceAll);

5) Utilisation remplace tout (cas 2)

int replaceAllCase2 = testString.length() - testString.replaceAll("\\.", "").length();
System.out.println("replaceAll (second case) = " + replaceAllCase2);

6) Utilisation Divisé

int split = testString.split("\\.",-1).length-1;
System.out.println("split = " + split);

7) en utilisant Java8 (cas 1)

long java8 = testString.chars().filter(ch -> ch =='.').count();
System.out.println("java8 = " + java8);

8) en utilisant Java8 (cas 2), peut être mieux pour unicode que le cas 1

long java8Case2 = testString.codePoints().filter(ch -> ch =='.').count();
System.out.println("java8 (second case) = " + java8Case2);

9) en utilisant StringTokenizer

int stringTokenizer = new StringTokenizer(" " +testString + " ", ".").countTokens()-1;
System.out.println("stringTokenizer = " + stringTokenizer);

De commentaire: Attention au StringTokenizer, pour abcd ça marchera mais pour un ... bc ... d ou ... abcd ou un .... b ...... c ..... d .. . ou etc. ça ne marchera pas. Ça va juste compter pour. entre des personnages juste une fois

Plus d'infos dans github

Test de performance (en utilisant JMH, mode = AverageTime, score 0.010 mieux que 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

188
2018-02-06 15:40



Tôt ou tard, quelque chose doit boucler. Il est beaucoup plus simple pour vous d'écrire la boucle (très simple) que d'utiliser quelque chose comme split ce qui est beaucoup plus puissant que ce dont vous avez besoin.

Par tout moyen encapsuler la boucle dans une méthode séparée, par ex.

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;
}

Ensuite, vous n'avez pas besoin d'avoir la boucle dans votre code principal - mais la boucle doit être là quelque part.


165
2017-11-09 14:38



J'ai eu une idée similaire à Mladen, mais le contraire ...

String s = "a.b.c.d";
int charCount = s.replaceAll("[^.]", "").length();
println(charCount);

59
2017-11-09 16:16



String s = "a.b.c.d";
int charCount = s.length() - s.replaceAll("\\.", "").length();

ReplaceAll (".") Remplacerait tous les caractères.

La solution de PhiLho utilise ReplaceAll ("[^.]", ""), qui n'a pas besoin d'être échappé, car [.] représente le caractère 'point' et non 'aucun caractère'.


34
2017-11-09 14:48



Ma solution "idiomatique à un interligne":

int count = "a.b.c.d".length() - "a.b.c.d".replace(".", "").length();

Je n'ai aucune idée pourquoi une solution qui utilise StringUtils est acceptée.


26
2017-11-13 19:30