Cómo contar palabras en una cadena en Java
Cuenta el número de palabras en una cadena Java usando trim y split con espacios en blanco, un matcher de regex, y evitando el split ingenuo.
Contar las palabras de una cadena parece trivial — dividir por espacios y contar las partes — pero la versión ingenua falla en cuanto la entrada tiene espacios iniciales, finales o repetidos. Este capítulo muestra las formas idiomáticas de contar palabras en Java, los casos límite que confunden a la gente y qué enfoque usar. Se basa en los fundamentos de Java Strings y String split and join.
Dividir por espacios en blanco (la opción predeterminada fiable)
La receta estándar es recortar la cadena y luego dividirla por uno o más caracteres de espacio en blanco con la regex \s+:
String text = " The quick brown fox ";
String trimmed = text.trim();
int words = trimmed.isEmpty() ? 0 : trimmed.split("\\s+").length;
System.out.println(words); // 4Dos detalles hacen que esto sea correcto. El trim() elimina los espacios iniciales y finales, porque split("\\s+") sobre una cadena que comienza con espacios en blanco produce un elemento vacío al inicio. El control con isEmpty() maneja la entrada en blanco: dividir "" devuelve un array de longitud 1, no 0, por lo que sin esta comprobación una cadena en blanco reportaría erróneamente una palabra.
El \\s es un literal de cadena Java para la regex \s, que coincide con espacios, tabulaciones y saltos de línea. El + significa "uno o más", de modo que cualquier secuencia de espacios en blanco cuenta como un único separador.
Evitar el split ingenuo con un solo espacio
Es tentador escribir text.split(" ").length, pero eso divide en exactamente un espacio y falla con entradas del mundo real:
String text = " The quick brown fox ";
System.out.println(text.split(" ").length); // 8, not 4Los dos espacios iniciales producen dos elementos vacíos al comienzo, y cada secuencia de tres espacios internos añade más — por lo que el array es ["", "", "The", "quick", "", "", "brown", "fox"], ocho elementos en lugar de cuatro. (El método split de Java descarta los strings vacíos al final, razón por la que los dos espacios finales no añaden nada.) Cada espacio doble y cada espacio inicial infla el contador. Dividir por " " solo es seguro cuando ya se sabe que la entrada es una línea delimitada por un único espacio sin espaciado extra — lo cual rara vez está garantizado.
Contar tokens con un matcher de regex
En lugar de dividir, puedes hacer coincidir los tokens de palabras directamente y contar las coincidencias. Esto evita por completo el problema de los elementos vacíos:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Matcher m = Pattern.compile("\\w+").matcher(text);
int count = 0;
while (m.find()) {
count++;
}\w+ coincide con secuencias de caracteres de palabra (letras, dígitos, guión bajo). Como busca palabras en lugar de separadores, los espacios en blanco iniciales, finales y repetidos son irrelevantes — no se necesita ningún control. La contrapartida es que \w excluye la puntuación, por lo que "well-known" con guión cuenta como dos tokens. Elige el patrón que se ajuste a tu definición de "palabra".
Si necesitas tokenizar un documento más largo o un flujo en lugar de una sola línea, el capítulo Java StringTokenizer cubre una clase diseñada específicamente para dividir texto en tokens.
| Enfoque | Maneja espacios extra/límite | Seguro con string vacío | Nota |
|---|---|---|---|
split(" ") | No | No | Falla con espacios repetidos |
trim().split("\\s+") | Sí | Con control isEmpty() | La opción predeterminada |
Matcher Pattern \w+ | Sí | Sí (cuenta 0) | Divide en puntuación |
Un ejemplo completo y funcional
Lo que se puede extraer de la ejecución:
Naive split length: 8demuestra quesplit(" ")sobreestima considerablemente porque cada espacio inicial y cada espacio dentro de una secuencia genera un elemento vacío extra en el array.Whitespace split: 4muestra quetrim().split("\\s+")colapsa cada secuencia de espacios en blanco y devuelve el conteo correcto.Regex matcher: 4confirma que el matcher\w+llega al mismo resultado sin necesidad de recortar ni de controles.Blank input words: 0demuestra por qué importa el controlisEmpty()— sin él, una entrada en blanco reportaría erróneamente una palabra.- Los tres métodos correctos coinciden en
4, por lo que la diferencia entre ellos es la robustez y la definición de "palabra", no el resultado con una entrada limpia.