Evaluación de las respuestas principales con un punto de referencia de rendimiento que confirma las preocupaciones de que la respuesta actual elegida haga costosas operaciones de expresiones regulares bajo el capó
Hasta la fecha, las respuestas proporcionadas vienen en 3 estilos principales (ignorando la respuesta de JavaScript;)):
- Use String.replace (charsToDelete, ""); que usa expresiones regulares debajo del capó
- Utilizar lambda
- Use una implementación simple de Java
En términos de tamaño de código, claramente el String.replace es el más conciso. La implementación simple de Java es un poco más pequeña y limpia (en mi humilde opinión) que la Lambda (no me malinterpreten, uso Lambdas a menudo cuando son apropiadas)
La velocidad de ejecución fue, en orden de más rápida a más lenta: implementación simple de Java, Lambda y luego String.replace () (que invoca expresiones regulares).
Con mucho, la implementación más rápida fue la implementación simple de Java ajustada para que preasigne el búfer StringBuilder a la longitud máxima posible del resultado y luego simplemente agregue caracteres al búfer que no están en la cadena "caracteres para eliminar". Esto evita las reasignaciones que se producirían para cadenas> 16 caracteres de longitud (la asignación predeterminada para StringBuilder) y evita el impacto de rendimiento "deslizar a la izquierda" de eliminar caracteres de una copia de la cadena que se produce es la implementación de Lambda.
El siguiente código ejecuta una prueba de referencia simple, ejecuta cada implementación 1,000,000 de veces y registra el tiempo transcurrido.
Los resultados exactos varían con cada ejecución, pero el orden de rendimiento nunca cambia:
Start simple Java implementation
Time: 157 ms
Start Lambda implementation
Time: 253 ms
Start String.replace implementation
Time: 634 ms
La implementación de Lambda (como se copió de la respuesta de Kaplan) puede ser más lenta porque realiza un "desplazamiento a la izquierda por uno" de todos los caracteres a la derecha del carácter que se está eliminando. Obviamente, esto empeoraría para cadenas más largas con muchos caracteres que requieren eliminación. También puede haber algo de sobrecarga en la implementación de Lambda en sí.
La implementación String.replace, utiliza expresiones regulares y realiza una "compilación" de expresiones regulares en cada llamada. Una optimización de esto sería usar regex directamente y almacenar en caché el patrón compilado para evitar el costo de compilarlo cada vez.
package com.sample;
import java.util.function.BiFunction;
import java.util.stream.IntStream;
public class Main {
static public String deleteCharsSimple(String fromString, String charsToDelete)
{
StringBuilder buf = new StringBuilder(fromString.length()); // Preallocate to max possible result length
for(int i = 0; i < fromString.length(); i++)
if (charsToDelete.indexOf(fromString.charAt(i)) < 0)
buf.append(fromString.charAt(i)); // char not in chars to delete so add it
return buf.toString();
}
static public String deleteCharsLambda(String fromString1, String charsToDelete)
{
BiFunction<String, String, String> deleteChars = (fromString, chars) -> {
StringBuilder buf = new StringBuilder(fromString);
IntStream.range(0, buf.length()).forEach(i -> {
while (i < buf.length() && chars.indexOf(buf.charAt(i)) >= 0)
buf.deleteCharAt(i);
});
return (buf.toString());
};
return deleteChars.apply(fromString1, charsToDelete);
}
static public String deleteCharsReplace(String fromString, String charsToDelete)
{
return fromString.replace(charsToDelete, "");
}
public static void main(String[] args)
{
String str = "XXXTextX XXto modifyX";
String charsToDelete = "X"; // Should only be one char as per OP's requirement
long start, end;
System.out.println("Start simple");
start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++)
deleteCharsSimple(str, charsToDelete);
end = System.currentTimeMillis();
System.out.println("Time: " + (end - start));
System.out.println("Start lambda");
start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++)
deleteCharsLambda(str, charsToDelete);
end = System.currentTimeMillis();
System.out.println("Time: " + (end - start));
System.out.println("Start replace");
start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++)
deleteCharsReplace(str, charsToDelete);
end = System.currentTimeMillis();
System.out.println("Time: " + (end - start));
}
}