스캐너와 StringTokenizer 및 String.Split
방금 Java의 스캐너 클래스에 대해 배웠으며 이제 StringTokenizer 및 String.Split과 어떻게 비교 / 경쟁하는지 궁금합니다. StringTokenizer 및 String.Split은 문자열에서만 작동하므로 스캐너를 문자열로 사용하려는 이유는 무엇입니까? 스캐너는 분할을위한 원 스톱 쇼핑이 목적입니까?
그들은 본질적으로 코스의 말입니다.
Scanner
문자열을 구문 분석하고 다른 유형의 데이터를 가져와야하는 경우를 위해 설계되었습니다. 매우 유연하지만 특정 표현식으로 구분 된 문자열 배열을 얻는 가장 간단한 API를 제공하지는 않습니다.String.split()
그리고Pattern.split()
당신이 후자를 수행하기위한 쉬운 구문을 제공하지만 본질적으로 그들은 모두 할 것이 있습니다. 결과 문자열을 구문 분석하거나 특정 토큰에 따라 구분 기호를 반쯤 변경하려는 경우 도움이되지 않습니다.StringTokenizer
보다 제한String.split()
적이고 사용하기가 조금 더 복잡합니다. 기본적으로 고정 하위 문자열로 구분 된 토큰을 가져 오기 위해 설계되었습니다. 이 제한으로 인해 약 2 배 빠릅니다String.split()
. ( 및 비교를String.split()
StringTokenizer
참조하십시오 .) 또한 정규 표현식 API보다 우선합니다String.split()
.
필자 는 일반적인 머신에서 몇 밀리 초 안에 수천 개의 문자열을String.split()
토큰 화 할 수 있다는 타이밍을 알 수 있습니다 . 또한 출력을 문자열 배열로 제공하는 것 보다 장점 이 있습니다. 이는 일반적으로 원하는 것입니다. 에서 제공 한대로을 사용하는 것은 대부분 "구문 적으로 까다로워"입니다. 이 관점에서 요즘은 약간의 공간 낭비이며,을 사용할 수도 있습니다 .StringTokenizer
Enumeration
StringTokenizer
StringTokenizer
String.split()
를 제거하여 시작하겠습니다 StringTokenizer
. 나이가 들었고 정규 표현식조차 지원하지 않습니다. 그 문서에는
StringTokenizer
새 코드에서는 사용을 권장하지 않지만 호환성 이유로 유지되는 레거시 클래스입니다. 이 기능을 원하는 사람은split
방법String
이나java.util.regex
패키지를 대신 사용하는 것이 좋습니다 .
이제 바로 버려 봅시다. 그 나뭇잎 split()
과 Scanner
. 그들 사이의 차이점은 무엇입니까?
우선, split()
배열을 반환하면 foreach 루프를 쉽게 사용할 수 있습니다.
for (String token : input.split("\\s+") { ... }
Scanner
더 스트림처럼 만들어집니다.
while (myScanner.hasNext()) {
String token = myScanner.next();
...
}
또는
while (myScanner.hasNextDouble()) {
double token = myScanner.nextDouble();
...
}
(이것은 다소 큰 API 를 가지고 있으므로 항상 간단한 것으로 제한되지 않는다고 생각하십시오.)
이 스트림 스타일 인터페이스는 구문 분석을 시작하기 전에 모든 입력이 없거나 (또는 얻을 수없는) 간단한 텍스트 파일 또는 콘솔 입력을 구문 분석하는 데 유용 할 수 있습니다.
개인적으로, 내가 기억할 수있는 유일한 시간 Scanner
은 명령 줄에서 사용자 입력을 얻어야 할 때 학교 프로젝트를위한 것입니다. 그것은 그런 종류의 작업을 쉽게 만듭니다. 그러나 내가 String
나누고 싶은 것을 가지고 있다면 , 거의 갈 필요가 없습니다 split()
.
StringTokenizer는 항상 존재했습니다. 가장 빠르지 만 열거 형 관용구가 다른 것만 큼 우아하지 않을 수 있습니다.
JDK 1.4에서 split이 존재하게되었습니다. 토크 나이저보다 느리지 만 String 클래스에서 호출 할 수 있으므로 사용하기가 더 쉽습니다.
스캐너는 JDK 1.5에있게되었습니다. 가장 유연하고 유명한 Cs scanf 함수 제품군과 동등한 기능을 지원하기 위해 Java API에서 오랜 간격을 메 웁니다.
분할 속도는 느리지 만 스캐너만큼 느리지는 않습니다. StringTokenizer가 분할보다 빠릅니다. 그러나 JFastParser https://github.com/hughperkins/jfastparser 에서 속도 부스트를 얻기 위해 유연성을 교환하여 속도를 두 배로 늘릴 수 있음을 알았습니다.
백만 배가 포함 된 문자열 테스트 :
Scanner: 10642 ms
Split: 715 ms
StringTokenizer: 544ms
JFastParser: 290ms
토큰 화하려는 String 객체가있는 경우 StringTokenizer보다 String의 split 메소드를 사용하는 것이 좋습니다. 파일이나 사용자와 같이 프로그램 외부의 소스에서 텍스트 데이터를 구문 분석하는 경우 검사기가 편리합니다.
String.split은 StringTokenizer보다 훨씬 느린 것 같습니다. split의 유일한 장점은 토큰 배열을 얻는 것입니다. 또한 정규식을 분할하여 사용할 수 있습니다. org.apache.commons.lang.StringUtils에는 두 개의 viz보다 훨씬 빠르게 작동하는 split 메소드가 있습니다. StringTokenizer 또는 String.split. 그러나 세 가지 모두에 대한 CPU 사용률은 거의 동일합니다. 따라서 CPU를 덜 사용하는 방법이 필요하지만 여전히 찾을 수 없습니다.
나는 최근에 성능이 중요한 상황에서 String.split ()의 나쁜 성능에 대한 실험을했습니다. 이 기능이 유용 할 수 있습니다.
http://eblog.chrononsystems.com/hidden-evils-of-javas-stringsplit-and-stringr
요점은 String.split ()이 매번 정규 표현식 패턴을 컴파일하므로 미리 컴파일 된 Pattern 객체를 사용하고이를 직접 사용하여 String에서 작동하는 경우에 비해 프로그램 속도가 느려질 수 있다는 것입니다.
기본 시나리오의 경우 Pattern.split ()을 제안하지만 최대 성능이 필요한 경우 (특히 Android에서 테스트 한 모든 솔루션이 매우 느림) 단일 문자로만 분할하면 이제 내 자신의 방법을 사용합니다.
public static ArrayList<String> splitBySingleChar(final char[] s,
final char splitChar) {
final ArrayList<String> result = new ArrayList<String>();
final int length = s.length;
int offset = 0;
int count = 0;
for (int i = 0; i < length; i++) {
if (s[i] == splitChar) {
if (count > 0) {
result.add(new String(s, offset, count));
}
offset = i + 1;
count = 0;
} else {
count++;
}
}
if (count > 0) {
result.add(new String(s, offset, count));
}
return result;
}
"abc".toCharArray ()를 사용하여 문자열의 문자 배열을 가져옵니다. 예를 들면 다음과 같습니다.
String s = " a bb ccc dddd eeeee ffffff ggggggg ";
ArrayList<String> result = splitBySingleChar(s.toCharArray(), ' ');
한 가지 중요한 차이점은 String.split ()과 Scanner가 모두 빈 문자열을 생성 할 수 있지만 StringTokenizer는이를 수행하지 않는다는 것입니다.
예를 들면 다음과 같습니다.
String str = "ab cd ef";
StringTokenizer st = new StringTokenizer(str, " ");
for (int i = 0; st.hasMoreTokens(); i++) System.out.println("#" + i + ": " + st.nextToken());
String[] split = str.split(" ");
for (int i = 0; i < split.length; i++) System.out.println("#" + i + ": " + split[i]);
Scanner sc = new Scanner(str).useDelimiter(" ");
for (int i = 0; sc.hasNext(); i++) System.out.println("#" + i + ": " + sc.next());
산출:
//StringTokenizer
#0: ab
#1: cd
#2: ef
//String.split()
#0: ab
#1: cd
#2:
#3: ef
//Scanner
#0: ab
#1: cd
#2:
#3: ef
This is because the delimiter for String.split() and Scanner.useDelimiter() is not just a string, but a regular expression. We can replace the delimiter " " with " +" in the example above to make them behave like StringTokenizer.
String.split() works very good but has its own boundaries, like if you wanted to split a string as shown below based on single or double pipe (|) symbol, it doesn't work. In this situation you can use StringTokenizer.
ABC|IJK
참고URL : https://stackoverflow.com/questions/691184/scanner-vs-stringtokenizer-vs-string-split
'development' 카테고리의 다른 글
포트 80 EC2 Amazon 웹 서비스 열기 (0) | 2020.06.11 |
---|---|
올바른 @author 태그를 얻기 위해 Eclipse에서 $ {user}를 어떻게 설정합니까? (0) | 2020.06.11 |
textarea가 입력 [type =“textarea”]이 아닌 이유는 무엇입니까? (0) | 2020.06.10 |
아무도 make for Java를 사용하지 않는 이유는 무엇입니까? (0) | 2020.06.10 |
xcode에서 Base SDK, iOS 배포 대상, 대상 및 프로젝트의 의미는 무엇입니까 (0) | 2020.06.10 |