Также необходимо отметить, то определение имен происходит перед разрешением перегрузки. Таким образом, если будет что-то с тем же именем в Вашей текущей области тогда, то это прекратит искать другие имена и попытается использовать их.
void bar() {};
class foo {
void bar(int) {};
void foobar() { bar(); } // won't compile needs ::bar()
void foobar(int i) { bar(i); } // ok
}
Оператор switch на самом деле не так уж плох. Ваш алгоритм линейен по отношению к длине телефонного номера. Код удобочитаем, и его довольно легко проверить путем проверки. Я бы не стал с этим связываться, кроме как добавить случай по умолчанию
для обработки ошибок. (Я не программист на Java, так что простите меня, если он называется чем-то другим.)
Если у вас есть , чтобы ускорить работу, предварительно инициализированная таблица, проиндексированная по символам, позволит избежать любых сравнений, кроме базовых. проверка ошибок. Вы даже можете избежать преобразования регистра, продублировав значения в таблице ( цифра ['A'] = цифра ['a'] = «2»;
). Стоимость инициализации таблицы будет амортизироваться по общему количеству преобразований.
Можно сделать это с использованием Apache Commons Lang StringUtils, как показано ниже:
String output = StringUtils.replaceChars(StringUtils.lowerCase(input),
"abcdefghijklmnopqrstuvwxyz",
"22233344455566677778889999");
Предполагая, что скорость не является вашей главной заботой, конечно, и вам нужно компактное решение;)
Используйте карту
, где клавиши - это буквы и цифры, а значение - это число на клавиатуре. (Таким образом, каждый номер клавиатуры будет проиндексирован тремя или четырьмя буквами и одной цифрой.)
Map<Character, Character> keypad = new HashMap<Character, Character>();
...
StringBuilder buf = new StringBuilder(inLetters.length());
for (int idx = 0; idx < inLetters.length(); ++idx) {
Character ch = keypad.get(inLetters.charAt(idx));
if (ch != null)
buf.append(ch);
}
Обновление: Мне было любопытно, будет ли справочная таблица с ручным кодированием работать лучше, чем переключатель с плотным набором
случаи. В ходе своего случайного тестирования я обнаружил, что следующий код является самым быстрым, что я мог придумать:
private static final char[] lut =
"0123456789:;<=>?@22233344455566677778889999[\\]^_`22233344455566677778889999".toCharArray();
private static final char min = lut[0];
String fastest(String letters)
{
int n = letters.length();
char[] buf = new char[n];
while (n-- > 0) {
int ch = letters.charAt(n) - min;
buf[n] = ((ch < 0) || (ch >= lut.length)) ? letters.charAt(n) : lut[ch];
}
return new String(buf);
}
Удивительно, но он был более чем в два раза быстрее, чем аналогичный код с использованием оператора switch (который скомпилирован в tablewitch
инструкция). Заметьте, это было просто для развлечения, но на моем ноутбуке, работающем в одном потоке, я мог преобразовать 10 миллионов 10-буквенных «чисел» примерно за 1,3 секунды. Я был очень удивлен, потому что, как я понимаю, tablewitch
работает по существу таким же образом, но я ожидал, что он будет быстрее, так как это инструкция JVM.
Конечно, если только мне не платили только за каждый из неограниченного количества телефонных номеров Я мог конвертировать, я бы никогда не стал писать такой код. Коммутатор гораздо более читабелен, работает как есть и, вероятно, получит бесплатное повышение производительности в некоторых будущих JVM.
Несомненно, наибольшее улучшение исходного кода происходит от использования StringBuilder
вместо конкатенации строк, и это никак не влияет на читаемость кода. Использование charAt
вместо преобразования входных данных в char []
также делает код более простым и понятным и также повышает производительность. В заключение,
Как насчет простого:
String convert(String inLetters) {
String digits = "22233344455566677778889999";
String alphas = "abcdefghijklmnopqrstuvwxyz";
String result = "";
for (char c : inLetters.toLowerCase().toCharArray()) {
int pos = alphas.indexOf(c);
result += (pos == -1 ? c : digits.charAt(pos));
}
return result;
}
Если вам нужно решение, которое не заставляет вас перечислять все буквы, вы можете сделать что-то вроде:
char convertedChar = c;
if (Character.isLetter(c)) {
//lowercase alphabet ASCII codes: 97 (a)-122 (z)
int charIndex = ((int)c) - 97;
//make adjustments to account for 's' and 'z'
if (charIndex >= 115) { //'s'
charIndex--;
}
if (charIndex == 121) { //'z'-1
charIndex--;
}
convertedChar = (char)(2 + (charIndex/3));
}
result += convertedChar;
Операторы Switch компилируются в форму, аналогичную операторам if-else, (каждый оператор case
по существу является if (c == '...' )
замаскированный тест), поэтому, хотя это визуально более компактно, чем каскадный if, этот тест для каждого символа, может быть или не быть никакого реального выигрыша в производительности.
Вы можете оптимизировать его, исключив некоторые сравнения. Ключ в том, что char
- это целочисленный тип (поэтому вы можете включить char
), чтобы вы могли использовать числовые операторы сравнения. и 'a Предполагая, что ваша строка inLetters
содержит только буквенно-цифровые символы, это должно работать ... (Все остальные символы будут проходить без изменений.)
String result = "";
for (char c : letters.toLowerCase().toCharArray()) {
if (c <= '9') result += c;
else if (c <= 'c') result += "2";
else if (c <= 'f') result += "3";
else if (c <= 'i') result += "4";
else if (c <= 'l') result += "5";
else if (c <= 'o') result += "6";
else if (c <= 's') result += "7";
else if (c <= 'v') result += "8";
else if (c <= 'z') result += "9";
else result += c;
}
Интересующие символы имеют шестнадцатеричные значения:' 0 '= 0x30 , ' 9 '= 0x39,' a '= 0x61 и' z '= 0x7a.
Изменить: Лучше использовать StringBuilder и append ()
в создать строку, но для небольших строк это вряд ли будет заметно быстрее. ( Закон Амдала демонстрирует, что фактическое ускорение, которое вы можете ожидать от оптимизации кода, ограничено процентом времени, фактически затраченным на этот код.) Я использовал только конкатенированные строки, чтобы сделать алгоритм понятным для OP.
Если вы запустите это 10 ^ 9 раз в узком цикле и несколько раз остановите его с Ctrl-break, я уверен, что почти каждый раз он будет глубоко в строковом классе, пытаясь выполнить одно из тех невинно выглядящих "+ = "операторы.