Quizás haya una forma más fácil de usar expresiones regulares en Java, pero yo no la encuentro. Usarlas en JavaScript, Python o Ruby es de las cosas que hacen atractivos estos lenguajes, pero en Java cuesta hacer natural lo natural.

Mi problematica es que tengo un servicio que retorna contenido HTML, y necesito dos cosas:

1. Saber cuantos caracteres del contenido pertenecen a TAGS HTML.

2. Retornar el contenido sin HTML, o sea en texto plano.

Por ejemplo, del texto:

"Presione <b><a href="javascript:void(0)">Aqui</a></b>..."

Debo retornar ["Presione Aqui", 40]. (40 es la cantidad de caracteres dentro de los tags).

Luce sencillo a simple vista, parsear el texto en busca de patrones que se corresponden con TAGS HTML substituyendo el patrón por un caracter blanco para eliminar los TAGS y contando el length de cada patrón devuelto. O sea se hace evidente el uso de Expresiones Regulares.

A continuación mi solución para que noten lo complicado que se hace programar con expresiones regulares en Java. Si alguien encuentra una forma más natural por favor no dude en enviarmela a través de un comentario.

Primero un contenedor de expresiones regulares compiladas

// regular expression Patterns (HTML TAGS) container
private static final Pattern[] HTML_TAG_REXP;
// init
static {
    HTML_TAG_REXP = new Pattern[] {
        Pattern.compile("<(a|A).*?>"),
        Pattern.compile("</(a|A)>"),
        Pattern.compile("<(b|B).*?>"),
        Pattern.compile("</(b|B)>"),
        Pattern.compile("<(i|I).*?>"),
        Pattern.compile("</(i|I)>"),
        Pattern.compile("<(p|P).*?>"),
        Pattern.compile("</(p|P)>"),
        Pattern.compile("<(img|IMG).*?>"),
        Pattern.compile("</(img|IMG)>"),
        Pattern.compile("<(stong|STRONG).*?>"),
        Pattern.compile("</(strong|STRONG)>"),
        Pattern.compile("<(h1|H1).*?>"),
        Pattern.compile("</(h1|H1)>"),
        Pattern.compile("<(h2|H2).*?>"),
        Pattern.compile("</(h2|H2)>"),
        Pattern.compile("<(h3|H3).*?>"),
        Pattern.compile("</(h3|H3)>"),
    };
}

Al compilarlas mejoramos la performance vs usar expresiones regulares literales. (Solo coloque algunos TAGS, pero basta con agregar más a la lista).

Y a continuación el método que pasado el contenido en HTML retorna un arreglo de objetos; donde en la primera posición va el contenido en texto plano (sin los TAGS HTML) y en la segunda posición la cantidad de caracteres que pertenecen a los TAGS.

...
/**
 * @param content
 * @return [String, Integer]
 */
private Object[] removeAndCountHtmlTags(String content) {
	String result = content;
	int htmlCharCount = 0;
	for (int i = 0; i < HTML_TAG_REXP.length; i++) {
		// create the matcher against the result
		Matcher m = HTML_TAG_REXP[i].matcher(result);
		// while send a message to find a match group is true
		while (m.find()) {
			LOG.info("matcher group - " + m.group(0));
			// count the number of chars that match
                        // the group
			htmlCharCount += m.group(0).length();
			// replace first ocurrence (eliminate tags)
			result = m.replaceFirst("");
                        // and send the message again to find the next
			m = HTML_TAG_REXP[i].matcher(result);
		}
	}
	return new Object[] {result, new Integer(htmlCharCount)};
}
...