Valutazione delle risposte principali con un benchmark delle prestazioni che conferma le preoccupazioni che l'attuale risposta scelta comporti costose operazioni regex sotto il cofano
Ad oggi le risposte fornite sono disponibili in 3 stili principali (ignorando la risposta JavaScript;)):
- Usa String.replace (charsToDelete, ""); che usa regex sotto il cofano
- Usa Lambda
- Usa una semplice implementazione Java
In termini di dimensioni del codice, String.replace è chiaramente il più conciso. La semplice implementazione di Java è leggermente più piccola e più pulita (IMHO) rispetto alla Lambda (non fraintendetemi: uso spesso Lambdas dove sono appropriate)
La velocità di esecuzione era, nell'ordine dal più veloce al più lento: semplice implementazione Java, Lambda e poi String.replace () (che invoca regex).
L'implementazione di gran lunga più rapida è stata la semplice implementazione Java messa a punto in modo tale che preallocasse il buffer StringBuilder alla massima lunghezza possibile dei risultati e quindi aggiungesse semplicemente i caratteri al buffer che non si trovano nella stringa "chars to delete". Questo evita qualsiasi riallocazione che si verificherebbe per stringhe> 16 caratteri di lunghezza (l'allocazione predefinita per StringBuilder) ed evita l'hit di prestazioni "slide left" dell'eliminazione di caratteri da una copia della stringa che si verifica è l'implementazione Lambda.
Il codice seguente esegue un semplice test di benchmark, eseguendo ogni implementazione 1.000.000 di volte e registra il tempo trascorso.
I risultati esatti variano ad ogni esecuzione ma l'ordine delle prestazioni non cambia mai:
Start simple Java implementation
Time: 157 ms
Start Lambda implementation
Time: 253 ms
Start String.replace implementation
Time: 634 ms
L'implementazione Lambda (come copiata dalla risposta di Kaplan) potrebbe essere più lenta perché esegue uno "spostamento lasciato da uno" di tutti i caratteri a destra del personaggio che viene eliminato. Ciò peggiorerebbe ovviamente per stringhe più lunghe con molti caratteri che richiedono la cancellazione. Inoltre potrebbe esserci un certo sovraccarico nell'implementazione Lambda stessa.
L'implementazione String.replace, usa regex e fa una regex "compilare" ad ogni chiamata. Un'ottimizzazione di questo sarebbe utilizzare regex direttamente e memorizzare nella cache il modello compilato per evitare il costo di compilarlo ogni volta.
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));
}
}