Manera simple de contar las ocurrencias de caracteres en una cadena

¿Hay una manera simple (en lugar de recorrer manualmente toda la cadena o bucle para indexOf) para encontrar cuántas veces aparece un carácter en una cadena?

Digamos que tenemos “abdsd3 $ asda $ asasdd $ sadas” y queremos que $ aparezca 3 veces.

String s = "..."; int counter = 0; for( int i=0; i 

Esta es definitivamente la manera más rápida. Los regex son mucho más lentos aquí, y posiblemente más difíciles de entender.

Estilo funcional (Java 8, solo por diversión):

 str.chars().filter(num -> num == '$').count() 

No es la forma óptima, sino simple de contar las ocurrencias:

 String s = "..."; int counter = s.split("\\$", -1).length - 1; 

Nota:

  • El signo de dólar es un símbolo especial de Expresión regular, por lo que se debe evitar con una barra invertida.
  • Una barra diagonal inversa es un símbolo especial para caracteres de escape como líneas nuevas, por lo que se debe escapar con una barra diagonal inversa.
  • El segundo argumento de división evita que las cadenas finales vacías se eliminen.

Puede utilizar Apache Commons ‘ StringUtils.countMatches(String string, String subStringToCount) .

Ya que está escaneando toda la cadena de todos modos, puede generar un recuento completo de caracteres y hacer cualquier cantidad de búsquedas, todo por el mismo costo de Oh (n):

 public static Map getCharFreq(String s) { Map charFreq = new HashMap(); if (s != null) { for (Character c : s.toCharArray()) { Integer count = charFreq.get(c); int newCount = (count==null ? 1 : count+1); charFreq.put(c, newCount); } } return charFreq; } // ... String s = "abdsd3$asda$asasdd$sadas"; Map counts = getCharFreq(s); counts.get('$'); // => 3 counts.get('a'); // => 7 counts.get('s'); // => 6 

Un conteo de frecuencia de caracteres es una tarea común para algunas aplicaciones (como la educación) pero no lo suficientemente general como para garantizar la inclusión con las API principales de Java. Como tal, probablemente necesitarás escribir tu propia función.

también puedes usar a para cada ciclo. Creo que es más simple de leer.

 int occurrences = 0; for(char c : yourString.toCharArray()){ if(c == '$'){ occurrences++; } } 

Atravesar la cadena es probablemente la más eficiente, aunque usar Regex para hacer esto puede generar un código de aspecto más limpio (aunque siempre puedes ocultar tu código de poligonal en una función).

Bueno, hay un montón de utilidades diferentes para esto, por ejemplo, Apache Commons Lang String Utils

pero al final, tiene que pasar por encima de la cadena para contar las ocurrencias de una forma u otra.

Tenga en cuenta también que el método countMatches anterior tiene la siguiente firma, por lo que también funcionará para las subcadenas.

public static int countMatches(String str, String sub)

La fuente de esto es (desde aquí ):

 public static int countMatches(String str, String sub) { if (isEmpty(str) || isEmpty(sub)) { return 0; } int count = 0; int idx = 0; while ((idx = str.indexOf(sub, idx)) != -1) { count++; idx += sub.length(); } return count; } 

Tenía curiosidad si estaban iterando sobre la cadena o usando Regex.

Creo que el “trazador de líneas” que esperabas obtener es este:

 "abdsd3$asda$asasdd$sadas".replaceAll( "[^$]*($)?", "$1" ).length(); 

Recuerde que los requisitos son:

(en lugar de atravesar manualmente toda la cadena o bucle para indexOf )

y permítanme agregar: que en el corazón de esta pregunta, parece que “ningún bucle” no se desea y no hay necesidad de velocidad. Creo que el subtexto de esta pregunta es factor de frialdad .

Algo un poco más funcional, sin Regex:

 public static int count(String s, char c) { return s.length()==0 ? 0 : (s.charAt(0)==c ? 1 : 0) + count(s.substring(1),c); } 

No es cola recursiva, por el bien de la claridad.

Puedes ver la ordenación de la cadena, tratarla como una matriz de caracteres, y luego hacer una búsqueda binaria modificada que cuente las ocurrencias. Pero estoy de acuerdo con @tofutim en que atravesarlo es lo más eficiente: O (N) versus O (N * logN) + O (logN)

Este es un código simple, pero por supuesto un poco más lento.

 String s = ...; int countDollar = s.length()-s.replaceAll("\\$","").length(); int counta = s.length()-s.replaceAll("a","").length(); 

Una respuesta aún mejor está aquí en una pregunta duplicada

Hay otra manera de contar la cantidad de caracteres en cada cadena. Suponiendo que tenemos una cadena como String str = "abfdvdvdfv"

A continuación, podemos contar la cantidad de veces que aparece cada personaje atravesando una sola vez como

 for (int i = 0; i < str.length(); i++) { if(null==map.get(str.charAt(i)+"")) { map.put(str.charAt(i)+"", new Integer(1)); } else { Integer count = map.get(str.charAt(i)+""); map.put(str.charAt(i)+"", count+1); } } 

Entonces podemos verificar la salida atravesando el mapa como

 for (Map.Entry entry:map.entrySet()) { System.out.println(entry.getKey()+" count is : "+entry.getValue()) } 
  public static int countChars(String input,char find){ if(input.indexOf(find) != -1){ return countChars(input.substring(0, input.indexOf(find)), find)+ countChars(input.substring(input.indexOf(find)+1),find) + 1; } else { return 0; } }