programing

스캐너와String Tokenizer vs.스트링분열되다

randomtip 2022. 9. 1. 22:40
반응형

스캐너와String Tokenizer vs.스트링분열되다

Java의 Scanner 클래스에 대해 방금 배웠는데 StringTokenizer 및 String과 비교가 되는지 궁금합니다.분할. StringTokenizer와 String을 알고 있습니다.분할은 문자열에서만 작동하는데 문자열에 스캐너를 사용해야 하는 이유는 무엇입니까?스캐너는 스플라이팅용 원스톱 쇼핑만을 목적으로 하고 있습니까?

그들은 본질적으로 코스를 위한 말이다.

  • Scanner는 문자열을 해석하여 다른 유형의 데이터를 추출할 필요가 있는 경우를 위해 설계되었습니다.이것은 매우 유연하지만 특정 표현식으로 구분된 문자열 배열을 얻기 위한 가장 간단한 API를 제공하지는 않습니다.
  • String.split()그리고.Pattern.split()후자를 위한 간단한 구문을 제공하지만 기본적으로는 그것뿐입니다.결과 문자열을 구문 분석하거나 특정 토큰에 따라 구분 기호를 중간에 변경하는 경우 도움이 되지 않습니다.
  • StringTokenizer보다 더 제한적이다String.split()및 사용하기에 다소 불안정합니다.기본적으로 고정 서브스트링으로 구분된 토큰을 추출하기 위해 설계되었습니다.이 제한으로 인해, 이것은 약 2배의 속도입니다.String.split(). (및의 비교를 참조해 주세요.)또한 정규 표현 API보다 앞서 있습니다.String.split()부품입니다.

제 타이밍을 보면 아시겠지만String.split()는 일반 머신에서 몇 밀리초 이내에 수천 개의 문자열을 토큰화할 수 있습니다.게다가, 이것은, 보다 유리합니다.StringTokenizer출력은 문자열 배열로 제공되며, 이는 일반적으로 사용자가 원하는 것입니다.의 사용방법Enumeration(에 의해 제공됨StringTokenizer는 대부분의 경우 너무 "구문적으로 호들갑"입니다.이런 관점에서 보면StringTokenizer요즘은 공간 낭비가 심해서String.split().

먼저 을(를) 제거하는 것으로 시작합니다.그것은 낡아서 정규 표현조차 지원하지 않는다.문서에는 다음과 같이 기재되어 있습니다.

StringTokenizer는 호환성을 위해 유지되는 레거시 클래스입니다.단, 새로운 코드에서는 사용이 권장되지 않습니다.이 기능을 사용하려는 사용자는 다음을 사용할 것을 권장합니다.split의 방법String또는java.util.regex패키지화해주세요.

그러니까 당장 버리자.그럼 이 남습니다.그 둘의 차이점은 무엇입니까?

하나는,split()는 단순히 배열을 반환하기 때문에 포어치 루프를 쉽게 사용할 수 있습니다.

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().

String Tokenizer는 항상 존재했습니다.모든 것 중에서 가장 빠르지만 열거형 사자성어는 다른 사자성어처럼 우아해 보이지 않을 수 있다.

스플릿이 JDK 1.4로 표시되었습니다.String 클래스에서 호출할 수 있기 때문에 토큰라이저보다 느리지만 사용하기 쉽습니다.

스캐너가 JDK 1.5가 되었다.이는 가장 유연하고 Java API의 오랜 공백을 메워 유명한 Cs scanf 함수 패밀리와 동등한 기능을 지원합니다.

분할은 느리지만 스캐너만큼 느리지는 않다.String Tokenizer는 분할보다 빠릅니다.그러나 JFastParser https://github.com/hughperkins/jfastparser에서 했던 것처럼 유연성을 교환함으로써 두 배의 속도를 얻을 수 있다는 것을 알게 되었습니다.

100만 배수를 포함하는 문자열에 대한 테스트:

Scanner: 10642 ms
Split: 715 ms
StringTokenizer: 544ms
JFastParser: 290ms

토큰화할 String 개체가 있는 경우 StringTokenizer보다 String의 분할 메서드를 사용하는 것이 좋습니다.파일이나 사용자 등 프로그램 외부의 원본에서 텍스트 데이터를 구문 분석하는 경우 스캐너가 유용합니다.

String.split은 StringTokenizer보다 훨씬 느린 것 같습니다.분할의 유일한 장점은 토큰 배열을 얻을 수 있다는 것입니다.또한 split.org.apache.commons.lang에서 임의의 정규식을 사용할 수도 있습니다.String Utils에는 2개의 viz 중 어느 것보다도 훨씬 빠르게 동작하는 분할 메서드가 있습니다.StringTokenizer 또는 String.split.그러나 이 세 가지 CPU 사용률은 거의 동일합니다.따라서 CPU를 덜 사용하는 방법도 필요한데, 아직 찾을 수 없습니다.

I recently did some experiments about the bad performance of String.split() in highly performance sensitive situations. You may find this useful.

Hidden evils of Java's String.split() and replace()

The gist is that String.split() compiles a Regular Expression pattern each time and can thus slow down your program, compared to if you use a precompiled Pattern object and use it directly to operate on a String.

One important difference is that both String.split() and Scanner can produce empty strings but StringTokenizer never does it.

For example:

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());

Output:

//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.

For the default scenarios I would suggest Pattern.split() as well but if you need maximum performance (especially on Android all solutions I tested are quite slow) and you only need to split by a single char, I now use my own method:

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;
}

Use "abc".toCharArray() to get the char array for a String. For example:

String s = "     a bb   ccc  dddd eeeee  ffffff    ggggggg ";
ArrayList<String> result = splitBySingleChar(s.toCharArray(), ' ');

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

ReferenceURL : https://stackoverflow.com/questions/691184/scanner-vs-stringtokenizer-vs-string-split

반응형