не меняется
самый быстрый способ убрать все непечатные символы изString
в Java?
До сих пор я пытался измерить 138-байтовую строку из 131 символа:
струныreplaceAll()
- самый медленный метод517009 результатов / секПрекомпилируйте Шаблон, затем используйте Matcher'sreplaceAll()
637836 результатов / секИспользуйте StringBuffer, получите кодовые точки, используяcodepointAt()
один за другим и добавить к StringBuffer711946 результатов / секИспользуйте StringBuffer, получайте символы используяcharAt()
один за другим и добавить к StringBuffer1052964 результатов / секПредварительно выделитьchar[]
буфер, получить символы с помощьюcharAt()
один за другим и заполнить этот буфер, затем преобразовать обратно в строку2022653 результатов / секПредварительно выделить 2char[]
буферов - старых и новых, получить все символы для существующей строки, используяgetChars()
, переберите старый буфер один за другим и заполните новый буфер, затем преобразуйте новый буфер в строку -моя самая быстрая версия2502502 результатов / секТо же самое с 2 буферами - только используяbyte[]
, getBytes()
и указав кодировку как "utf-8"857485 результатов / секТо же самое с 2byte[]
буферы, но указав кодировку как константуCharset.forName("utf-8")
791076 результатов / секТо же самое с 2byte[]
буферы, но указав кодировку как локальную 1-байтовую кодировку (едва ли это нормальная вещь)370164 результатов / секМоя лучшая попытка была следующей:
char[] oldChars = new char[s.length()];
s.getChars(0, s.length(), oldChars, 0);
char[] newChars = new char[s.length()];
int newLen = 0;
for (int j = 0; j < s.length(); j++) {
char ch = oldChars[j];
if (ch >= ' ') {
newChars[newLen] = ch;
newLen++;
}
}
s = new String(newChars, 0, newLen);
Есть мысли о том, как сделать это еще быстрее?
Бонусные баллы за ответ на очень странный вопрос: почему использование имени кодировки "utf-8" напрямую дает лучшую производительность, чем использование предварительно выделенного статического константCharset.forName("utf-8")
?
Я старался изо всех сил собрать все предложенные решения и их кросс-мутации и опубликовал его какнебольшая структура бенчмаркинга в github, В настоящее время в нем 17 алгоритмов. Один из них «особенный» -Voo1 алгоритм (предоставлено пользователем SO Voo) использует сложные приемы отражения, таким образом, достигая звездных скоростей, но он портит состояние строк JVM, таким образом, он тестируется отдельно.
Вы можете проверить это и запустить, чтобы определить результаты на вашем ящике. Вот резюме результатов, которые я получил на моем. Это спецификации:
Debian sidLinux 2.6.39-2-amd64 (x86_64)Java установлена из пакетаsun-java6-jdk-6.24-1
JVM идентифицирует себя какJava (TM) SE Runtime Environment (сборка 1.6.0_24-b07)Java HotSpot (TM) 64-разрядная серверная виртуальная машина (сборка 19.1-b02, смешанный режим)Разные алгоритмы показывают совершенно разные результаты при разном наборе входных данных. Я провел тест в 3 режимах:
Та же строкаЭтот режим работает с одной строкой, предоставленнойStringSource
класс как константа. Вскрытие является:
Ops / s │ Algorithm ──────────┼────────────────────────────── 6 535 947 │ Voo1 ──────────┼────────────────────────────── 5 350 454 │ RatchetFreak2EdStaub1GreyCat1 5 249 343 │ EdStaub1 5 002 501 │ EdStaub1GreyCat1 4 859 086 │ ArrayOfCharFromStringCharAt 4 295 532 │ RatchetFreak1 4 045 307 │ ArrayOfCharFromArrayOfChar 2 790 178 │ RatchetFreak2EdStaub1GreyCat2 2 583 311 │ RatchetFreak2 1 274 859 │ StringBuilderChar 1 138 174 │ StringBuilderCodePoint 994 727 │ ArrayOfByteUTF8String 918 611 │ ArrayOfByteUTF8Const 756 086 │ MatcherReplace 598 945 │ StringReplaceAll 460 045 │ ArrayOfByteWindows1251
В намеченной форме:Та же диаграмма с одной строкой http://www.greycat.ru/img/os-chart-single.png
Несколько строк, 100% строк содержат управляющие символыПоставщик исходной строки предварительно сгенерировал множество случайных строк, используя набор символов (0..127) - таким образом, почти все строки содержали хотя бы один управляющий символ. Алгоритмы получали строки из этого предварительно сгенерированного массива циклически.
Ops / s │ Algorithm ──────────┼────────────────────────────── 2 123 142 │ Voo1 ──────────┼────────────────────────────── 1 782 214 │ EdStaub1 1 776 199 │ EdStaub1GreyCat1 1 694 628 │ ArrayOfCharFromStringCharAt 1 481 481 │ ArrayOfCharFromArrayOfChar 1 460 067 │ RatchetFreak2EdStaub1GreyCat1 1 438 435 │ RatchetFreak2EdStaub1GreyCat2 1 366 494 │ RatchetFreak2 1 349 710 │ RatchetFreak1 893 176 │ ArrayOfByteUTF8String 817 127 │ ArrayOfByteUTF8Const 778 089 │ StringBuilderChar 734 754 │ StringBuilderCodePoint 377 829 │ ArrayOfByteWindows1251 224 140 │ MatcherReplace 211 104 │ StringReplaceAll
В намеченной форме:Несколько струн, 100% концентрация http://www.greycat.ru/img/os-chart-multi100.png
Несколько строк, 1% строк содержат управляющие символыТо же, что и в предыдущем случае, но только 1% строк было сгенерировано с управляющими символами - остальные 99% были сгенерированы при использовании набора символов [32..127], поэтому они вообще не могли содержать управляющие символы. Эта синтетическая нагрузка наиболее близка к реальному применению этого алгоритма у меня дома.
Ops / s │ Algorithm ──────────┼────────────────────────────── 3 711 952 │ Voo1 ──────────┼────────────────────────────── 2 851 440 │ EdStaub1GreyCat1 2 455 796 │ EdStaub1 2 426 007 │ ArrayOfCharFromStringCharAt 2 347 969 │ RatchetFreak2EdStaub1GreyCat2 2 242 152 │ RatchetFreak1 2 171 553 │ ArrayOfCharFromArrayOfChar 1 922 707 │ RatchetFreak2EdStaub1GreyCat1 1 857 010 │ RatchetFreak2 1 023 751 │ ArrayOfByteUTF8String 939 055 │ StringBuilderChar 907 194 │ ArrayOfByteUTF8Const 841 963 │ StringBuilderCodePoint 606 465 │ MatcherReplace 501 555 │ StringReplaceAll 381 185 │ ArrayOfByteWindows1251
В намеченной форме:Несколько строк, 1% концентрация http://www.greycat.ru/img/os-chart-multi1.png
Мне очень трудно определиться с тем, кто дал лучший ответ, но, учитывая, что лучшее решение для реального приложения было предоставлено / вдохновлено Эдом Стаубом, я думаю, было бы справедливо отметить его ответ. Спасибо всем, кто принял участие в этом, ваш вклад был очень полезным и неоценимым. Не стесняйтесь запускать набор тестов на своем компьютере и предлагать еще лучшие решения (рабочий JNI-решение, кто-нибудь?).
РекомендацииGitHub репозиторий с набором тестов