Avaliação das principais respostas com uma referência de desempenho que confirma preocupações de que a resposta escolhida atual faça operações regex dispendiosas sob o capô
Até o momento, as respostas fornecidas estão em três estilos principais (ignorando a resposta JavaScript;)):
- Use String.replace (charsToDelete, ""); que usa regex sob o capô
- Use Lambda
- Use implementação Java simples
Em termos de tamanho do código, claramente o String.replace é o mais conciso. A implementação Java simples é um pouco menor e mais limpa (IMHO) do que o Lambda (não me interpretem mal - eu uso o Lambdas sempre que apropriado)
A velocidade de execução foi, na ordem do mais rápido para o mais lento: implementação simples de Java, Lambda e String.replace () (que chama regex).
De longe, a implementação mais rápida foi a simples implementação Java ajustada para pré-alocar o buffer StringBuilder ao tamanho máximo possível do resultado e, em seguida, simplesmente anexa caracteres ao buffer que não está na string "chars to delete". Isso evita qualquer realocação que ocorreria para Strings> 16 caracteres de comprimento (a alocação padrão para StringBuilder) e evita o impacto de desempenho "deslizar para a esquerda" ao excluir caracteres de uma cópia da string que ocorre é a implementação do Lambda.
O código abaixo executa um teste de benchmark simples, executando cada implementação 1.000.000 de vezes e registra o tempo decorrido.
Os resultados exatos variam a cada execução, mas a ordem do desempenho nunca muda:
Start simple Java implementation
Time: 157 ms
Start Lambda implementation
Time: 253 ms
Start String.replace implementation
Time: 634 ms
A implementação do Lambda (como copiada da resposta da Kaplan) pode ser mais lenta porque executa um "deslocamento deixado por um" de todos os caracteres à direita do caractere sendo excluído. Obviamente, isso pioraria para cadeias mais longas, com muitos caracteres exigindo exclusão. Também pode haver alguma sobrecarga na própria implementação do Lambda.
A implementação String.replace, usa regex e faz uma regex "compilar" a cada chamada. Uma otimização disso seria usar o regex diretamente e armazenar em cache o padrão compilado para evitar o custo de compilá-lo a 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));
}
}