การประเมินคำตอบหลักด้วยเกณฑ์มาตรฐานประสิทธิภาพซึ่งยืนยันความกังวลว่าคำตอบที่เลือกในปัจจุบันทำให้การดำเนินการ regex ราคาแพงภายใต้ประทุน
ในวันที่คำตอบที่ให้มามี 3 รูปแบบหลัก (ละเว้นคำตอบ JavaScript;)):
- ใช้ String.replace (charsToDelete, ""); ซึ่งใช้ regex ภายใต้ประทุน
- ใช้แลมบ์ดา
- ใช้การติดตั้ง Java อย่างง่าย
ในแง่ของขนาดรหัสอย่างชัดเจน String.replace เป็นตัวย่อที่สุด การติดตั้ง Java อย่างง่ายมีขนาดเล็กกว่าและสะอาดกว่า (มากกว่า IMHO) มากกว่า Lambda (อย่าเข้าใจฉันผิด - ฉันใช้ Lambdas บ่อยครั้งในที่ที่เหมาะสม)
ความเร็วในการประมวลผลคือช้าที่สุดไปจนถึงช้าที่สุด: การติดตั้ง Java อย่างง่ายแลมบ์ดาแล้วตามด้วย String.replace () (ที่เรียกใช้ regex)
การใช้งานที่เร็วที่สุดคือการปรับใช้ Java อย่างง่ายเพื่อให้สามารถจัดสรรบัฟเฟอร์ StringBuilder ล่วงหน้าให้กับความยาวผลลัพธ์สูงสุดที่เป็นไปได้จากนั้นจึงผนวกตัวอักษรต่อท้ายบัฟเฟอร์ที่ไม่ได้อยู่ในสตริง "ตัวอักษรเพื่อลบ" สิ่งนี้จะหลีกเลี่ยงการจัดสรรใหม่ที่จะเกิดขึ้นสำหรับ Strings> 16 chars ที่มีความยาว (การจัดสรรเริ่มต้นสำหรับ StringBuilder) และจะหลีกเลี่ยงการทำงานที่ "ภาพนิ่งซ้าย" ในการลบอักขระจากการคัดลอกสตริงที่เกิดขึ้นคือการนำ Lambda
โค้ดด้านล่างนี้ทำการทดสอบเกณฑ์มาตรฐานอย่างง่ายโดยเรียกใช้การติดตั้ง 1,000,000 ครั้งและบันทึกเวลา
ผลลัพธ์ที่แน่นอนแตกต่างกันไปในการทำงานแต่ละครั้ง แต่ลำดับของประสิทธิภาพไม่เคยเปลี่ยนแปลง:
Start simple Java implementation
Time: 157 ms
Start Lambda implementation
Time: 253 ms
Start String.replace implementation
Time: 634 ms
การปรับใช้แลมบ์ดา (ดังที่คัดลอกมาจากคำตอบของ Kaplan) อาจช้าลงเพราะดำเนินการ "เลื่อนซ้ายหนึ่ง" ของตัวละครทั้งหมดไปทางขวาของตัวละครที่ถูกลบ เห็นได้ชัดว่านี่จะแย่ลงสำหรับสตริงที่ยาวขึ้นซึ่งมีตัวละครจำนวนมากที่ต้องการลบ นอกจากนี้ยังอาจมีค่าใช้จ่ายในการใช้งานแลมบ์ดาเอง
การใช้งาน String.replace ใช้ regex และทำการ "คอมไพล์" regex ที่การโทรแต่ละครั้ง การเพิ่มประสิทธิภาพของสิ่งนี้จะใช้ regex โดยตรงและแคชรูปแบบการรวบรวมเพื่อหลีกเลี่ยงค่าใช้จ่ายในการรวบรวมในแต่ละครั้ง
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));
}
}