Что такое эффективный способ замены многих символов в строке?
Обработка строк в Java - это то, что я пытаюсь научиться делать хорошо. В настоящее время я хочу взять строку и заменить любые символы, которые я нахожу.
Вот моя текущая неэффективная (и вроде бы глупая IMO) функция. Это было написано просто для работы.
public String convertWord(String word)
{
return word.toLowerCase().replace('á', 'a')
.replace('é', 'e')
.replace('í', 'i')
.replace('ú', 'u')
.replace('ý', 'y')
.replace('ð', 'd')
.replace('ó', 'o')
.replace('ö', 'o')
.replaceAll("[-]", "")
.replaceAll("[.]", "")
.replaceAll("[/]", "")
.replaceAll("[æ]", "ae")
.replaceAll("[þ]", "th");
}
Я побежал 1.000.000 трасс, и это заняло 8182ms. Итак, как мне приступить к изменению этой функции, чтобы сделать ее более эффективной?
Решение найдено:
Преобразование функции в этот
public String convertWord(String word)
{
StringBuilder sb = new StringBuilder();
char[] charArr = word.toLowerCase().toCharArray();
for(int i = 0; i < charArr.length; i++)
{
// Single character case
if(charArr[i] == 'á')
{
sb.append('a');
}
// Char to two characters
else if(charArr[i] == 'þ')
{
sb.append("th");
}
// Remove
else if(charArr[i] == '-')
{
}
// Base case
else
{
sb.append(word.charAt(i));
}
}
return sb.toString();
}
Запуск этой функции 1.000.000 раз занимает 518 мс. Поэтому я считаю, что это достаточно эффективно. Спасибо за помощь ребятам:)
Ответы
Ответ 1
Вы можете создать таблицу String [], которая имеет длину Character.MAX_VALUE. (Включая отображение в нижний регистр)
По мере усложнения условий замены время их выполнения останется прежним.
private static final String[] REPLACEMENT = new String[Character.MAX_VALUE+1];
static {
for(int i=Character.MIN_VALUE;i<=Character.MAX_VALUE;i++)
REPLACEMENT[i] = Character.toString(Character.toLowerCase((char) i));
// substitute
REPLACEMENT['á'] = "a";
// remove
REPLACEMENT['-'] = "";
// expand
REPLACEMENT['æ'] = "ae";
}
public String convertWord(String word) {
StringBuilder sb = new StringBuilder(word.length());
for(int i=0;i<word.length();i++)
sb.append(REPLACEMENT[word.charAt(i)]);
return sb.toString();
}
Ответ 2
Мое предложение было бы:
- Преобразование строки в массив char []
- Запуск через массив, тестирование каждого символа один за другим (например, с помощью оператора switch) и его замена при необходимости
- Преобразуйте массив char [] обратно в строку
Я думаю, что это, вероятно, самая быстрая производительность, которую вы получите в чистой Java.
EDIT: Я заметил, что вы делаете некоторые изменения, которые изменяют длину строки. В этом случае применяется тот же принцип, однако вам нужно сохранить два массива и прирастить как индекс источника, так и индекс назначения отдельно. Вам также может потребоваться изменить размер целевого массива, если вы исчерпали целевое пространство (т.е. Перераспределите более крупный массив и arraycopy существующий целевой массив в него)
Ответ 3
Моя реализация основана на таблице поиска.
public static String convertWord(String str) {
char[] words = str.toCharArray();
char[] find = {'á','é','ú','ý','ð','ó','ö','æ','þ','-','.',
'/'};
String[] replace = {"a","e","u","y","d","o","o","ae","th"};
StringBuilder out = new StringBuilder(str.length());
for (int i = 0; i < words.length; i++) {
boolean matchFailed = true;
for(int w = 0; w < find.length; w++) {
if(words[i] == find[w]) {
if(w < replace.length) {
out.append(replace[w]);
}
matchFailed = false;
break;
}
}
if(matchFailed) out.append(words[i]);
}
return out.toString();
}
Ответ 4
Мой первый выбор - использовать StringBuilder
, потому что вам нужно удалить некоторые символы из строки.
Второй выбор заключается в том, чтобы итерация выбрала массив символов и добавила обработанный char в другой массив из натурального размера строки. Затем вам нужно будет скопировать массив, чтобы обрезать возможные неиспользуемые позиции.
После этого я бы сделал некоторые тесты производительности, чтобы увидеть, что ведьма лучше.
Ответ 5
Я сомневаюсь, что вы действительно можете ускорить "замену персонажа". Что касается замены регулярного выражения, вы можете заранее скомпилировать регулярные выражения
Ответ 6
Используйте функцию String.replaceAll.
Хорошая статья похожа на то, что вы хотите: ссылка
Ответ 7
Каждый раз, когда у нас возникают подобные проблемы, мы используем регулярные выражения, которые, безусловно, являются самым быстрым способом справиться с тем, что вы пытаетесь сделать.
Вы уже пробовали регулярные выражения?
Ответ 8
То, что я вижу неэффективным, заключается в том, что вы снова проверите символы, которые уже были заменены, что бесполезно.
Я бы получил charArray экземпляра String, перебирал его и для каждого символьного спама серию if-else вроде этого:
char[] array = word.toCharArray();
for(int i=0; i<array.length; ++i){
char currentChar = array[i];
if(currentChar.equals('é'))
array[i] = 'e';
else if(currentChar.equals('ö'))
array[i] = 'o';
else if(//...
}