String
Java 에서 인쇄 할 수없는 모든 문자를 제거하는 가장 빠른 방법은 무엇입니까 ?
지금까지 138 바이트, 131 자 문자열을 시도하고 측정했습니다.
- 문자열
replaceAll()
- 가장 느린 방법- 517009 결과 / 초
- 패턴을 미리 컴파일 한 다음 Matcher의
replaceAll()
- 637836 결과 / 초
- StringBuffer 사용,
codepointAt()
하나씩 사용하여 코드 포인트 가져 오기 및 StringBuffer에 추가- 711946 개의 결과 / 초
- StringBuffer를 사용하고,
charAt()
하나씩 사용하여 문자를 얻고 StringBuffer에 추가하십시오.- 1052964 결과 / 초
char[]
버퍼를 미리 할당하고 ,charAt()
하나씩 사용하여 문자를 가져 와서이 버퍼를 채운 다음 다시 문자열로 변환합니다.- 2022653 개의 결과 / 초
- 2 개 미리 할당
char[]
버퍼 - 사용하여 한 번에 과거와는 문자열을 기존의 모든 문자를 얻을getChars()
반복,이 위에 오래 된 버퍼 일대일로 새로운 버퍼를 채우기, 다음 문자열에 새로운 버퍼를 변환 - 내 자신의 빠른 버전을- 2502502 개 결과 / 초
- 만 사용 -이 버퍼와 같은 것들
byte[]
,getBytes()
그리고 "UTF-8"로 인코딩을 지정- 857485 결과 / 초
- 2 개의
byte[]
버퍼가있는 동일한 항목 이지만 인코딩을 상수로 지정Charset.forName("utf-8")
- 791076 개의 결과 / 초
- 2 개의
byte[]
버퍼가있는 동일한 항목 이지만 인코딩을 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"문자셋 이름을 사용하면 사전 할당 된 정적 const를 사용하는 것보다 직접적으로 더 나은 성능을 얻을 수있는 이유는 Charset.forName("utf-8")
무엇입니까?
최신 정보
- 래칫 괴물의 제안 은 인상적인 3105590 결과 / 초 성능, + 24 % 향상을 제공합니다!
- Ed Staub의 제안은 또 다른 개선을 가져 왔습니다. 3471017 결과 / 초, 이전 최고 대비 + 12 %.
업데이트 2
나는 모든 제안 된 솔루션과 그 교차 돌연변이를 수집하기 위해 최선을 다 했으며이를 github에 작은 벤치마킹 프레임 워크 로 게시했습니다 . 현재 17 개의 알고리즘이 있습니다. 그중 하나는 "특별한" -Voo1 알고리즘 ( SO 사용자 Voo 제공 )은 복잡한 반사 트릭을 사용하여 뛰어난 속도를 달성하지만 JVM 문자열의 상태를 엉망으로 만들어 별도로 벤치마킹됩니다.
확인하고 실행하여 상자에 대한 결과를 확인할 수 있습니다. 다음은 제가 얻은 결과의 요약입니다. 사양 :
- 데비안 sid
- Linux 2.6.39-2-amd64 (x86_64)
- 패키지에서 설치된 Java
sun-java6-jdk-6.24-1
, JVM은 자신을 다음과 같이 식별합니다.- Java (TM) SE 런타임 환경 (빌드 1.6.0_24-b07)
- Java HotSpot (TM) 64 비트 서버 VM (빌드 19.1-b02, 혼합 모드)
서로 다른 알고리즘은 서로 다른 입력 데이터 세트가 주어지면 궁극적으로 서로 다른 결과를 보여줍니다. 3 가지 모드로 벤치 마크를 실행했습니다.
동일한 단일 문자열
이 모드는 StringSource
클래스가 상수로 제공하는 동일한 단일 문자열에서 작동합니다 . 대결은 다음과 같습니다.
Ops / s │ 알고리즘 ──────────┼────────────────────────────── 6535947 │ Voo1 ──────────┼────────────────────────────── 5350454 │ RatchetFreak2EdStaub1GreyCat1 5249 343 │ EdStaub1 5002501 │ EdStaub1GreyCat1 4859086 │ ArrayOfCharFromStringCharAt 4295532 │ RatchetFreak1 4045307 │ ArrayOfCharFromArrayOfChar 2790178 │ RatchetFreak2EdStaub1GreyCat2 2583311 │ RatchetFreak2 1274 859 │ StringBuilderChar 1138174 │ StringBuilderCodePoint 994727 │ ArrayOfByteUTF8String 918611 │ ArrayOfByteUTF8Const 756 086 │ MatcherReplace 598945 │ StringReplaceAll 460 045 │ ArrayOfByteWindows1251
차트 형식 :
(출처 : greycat.ru )
여러 문자열, 문자열의 100 %에 제어 문자가 포함됨
소스 문자열 공급자는 (0..127) 문자 집합을 사용하여 많은 임의의 문자열을 미리 생성했습니다. 따라서 거의 모든 문자열에 하나 이상의 제어 문자가 포함되었습니다. 알고리즘은이 사전 생성 된 배열에서 라운드 로빈 방식으로 문자열을 수신했습니다.
Ops / s │ 알고리즘 ──────────┼────────────────────────────── 2123142 │ Voo1 ──────────┼────────────────────────────── 1782214 │ EdStaub1 1776199 │ EdStaub1GreyCat1 1694628 │ ArrayOfCharFromStringCharAt 1481 481 │ ArrayOfCharFromArrayOfChar 1460067 │ RatchetFreak2EdStaub1GreyCat1 1438435 │ RatchetFreak2EdStaub1GreyCat2 1366 494 │ RatchetFreak2 1,349,710 │ RatchetFreak1 893176 │ ArrayOfByteUTF8String 817127 │ ArrayOfByteUTF8Const 778 089 │ StringBuilderChar 734754 │ StringBuilderCodePoint 377 829 │ ArrayOfByteWindows1251 224140 │ MatcherReplace 211104 │ StringReplaceAll
차트 형식 :
(출처 : greycat.ru )
여러 문자열, 문자열의 1 %에 제어 문자가 포함됨
이전과 동일하지만 제어 문자로 문자열의 1 % 만 생성되었습니다. 다른 99 %는 [32..127] 문자 집합을 사용하여 생성되었으므로 제어 문자를 전혀 포함 할 수 없습니다. 이 합성 부하는 제 자리에서이 알고리즘의 실제 적용에 가장 가깝습니다.
Ops / s │ 알고리즘 ──────────┼────────────────────────────── 3711952 │ Voo1 ──────────┼────────────────────────────── 2851440 │ EdStaub1GreyCat1 2455796 │ EdStaub1 2426007 │ ArrayOfCharFromStringCharAt 2347969 │ RatchetFreak2EdStaub1GreyCat2 2242152 │ RatchetFreak1 2171 553 │ ArrayOfCharFromArrayOfChar 1922707 │ RatchetFreak2EdStaub1GreyCat1 1857010 │ RatchetFreak2 1,023 751 │ ArrayOfByteUTF8String 939 055 │ StringBuilderChar 907194 │ ArrayOfByteUTF8Const 841963 │ StringBuilderCodePoint 606465 │ MatcherReplace 501555 │ StringReplaceAll 381185 │ ArrayOfByteWindows1251
차트 형식 :
(출처 : greycat.ru )
누가 가장 좋은 답변을 제공했는지 결정하기가 매우 어렵지만 실제 응용 프로그램이 Ed Staub에 의해 제공되고 영감을받은 실제 응용 프로그램을 고려할 때 그의 답변을 표시하는 것이 공정 할 것 같습니다. 참여 해주신 모든 분들께 감사 드리며, 귀하의 의견은 매우 유용하고 귀중했습니다. 상자에서 테스트 스위트를 자유롭게 실행하고 더 나은 솔루션을 제안하십시오 (JNI 솔루션을 사용하고 있습니까?).
참고 문헌
- 벤치마킹 제품군이있는 GitHub 저장소