어떤 가장 쉽/최선/가 올바른 방법으로 반복의 캐릭터를 통해 문자열에서 Java?

StackOverflow https://stackoverflow.com/questions/196830

문제

StringTokenizer?변환 Stringchar[] 고 반복되는?다른 뭔가?

도움이 되었습니까?

해결책

나는 루프를 사용하여 문자열을 반복하고 사용합니다. charAt() 각 캐릭터가 검사하도록합니다. 문자열은 배열로 구현되므로 charAt() 방법은 일정한 시간 작동입니다.

String s = "...stuff...";

for (int i = 0; i < s.length(); i++){
    char c = s.charAt(i);        
    //Process char
}

그것이 내가 할 일입니다. 나에게 가장 쉬운 것 같습니다.

정확성이 진행되는 한, 나는 그것이 여기에 존재한다고 믿지 않습니다. 그것은 모두 당신의 개인 스타일을 기반으로합니다.

다른 팁

두 가지 옵션

for(int i = 0, n = s.length() ; i < n ; i++) { 
    char c = s.charAt(i); 
}

또는

for(char c : s.toCharArray()) {
    // process c
}

첫 번째는 아마도 더 빠르고, 두 번째는 아마도 더 읽기 쉬울 것입니다.

BMP 외부의 캐릭터를 다루는 경우 여기에 설명 된 다른 기술의 대부분을 기록하십시오 (유니 코드 기본 다국어 평면), 즉 코드 포인트 U0000-Fuffff 범위 외부에 있습니다. 이 외부의 코드 포인트는 대부분 죽은 언어에 할당되기 때문에 거의 발생하지 않습니다. 그러나이 외부에는 유용한 문자가 있습니다. 예를 들어 수학 표기법에 사용되는 일부 코드 포인트 및 일부는 중국어로 적절한 이름을 인코딩하는 데 사용됩니다.

이 경우 코드는 다음과 같습니다.

String str = "....";
int offset = 0, strLen = str.length();
while (offset < strLen) {
  int curChar = str.codePointAt(offset);
  offset += Character.charCount(curChar);
  // do something with curChar
}

그만큼 Character.charCount(int) 방법에는 Java 5+가 필요합니다.

원천: http://mindprod.com/jgloss/codepoint.html

나는 StringTokenizer가 여기에서 과잉이라는 데 동의합니다. 실제로 나는 위의 제안을 시도하고 시간이 걸렸습니다.

내 테스트는 상당히 간단했습니다. 약 백만 문자가있는 StringBuilder를 만들고 문자열로 변환 한 다음 charat () / charat ()로 각각을 charat ()로 변환 한 후 (물론 컴파일러가 전체 루프를 최적화 할 수 없도록 문자열에서 무언가를하십시오 :-)).

2.6 GHZ PowerBook (Mac :-)) 및 JDK 1.5의 결과 :

  • 테스트 1 : charat + string-> 3138msec
  • 테스트 2 : 배열로 변환 된 문자열 -> 9568msec
  • 테스트 3 : StringBuilder charat-> 3536msec
  • 테스트 4 : 캐릭터 및 문자열 -> 12151msec

결과가 크게 다르기 때문에 가장 간단한 방법도 가장 빠른 방법 인 것 같습니다. 흥미롭게도, StringBuilder의 charat ()는 문자열보다 약간 느린 것 같습니다.

BTW 나는 ' uffff'캐릭터의 남용을 정말 끔찍한 해킹으로 간주 할 때 캐릭터를 사용하지 않는 것이 좋습니다. 큰 프로젝트에는 항상 두 가지 다른 목적으로 동일한 종류의 해킹을 사용하는 두 사람이 있으며 코드는 정말 신비롭게 충돌합니다.

테스트 중 하나입니다.

    int count = 1000;
    ...

    System.out.println("Test 1: charAt + String");
    long t = System.currentTimeMillis();
    int sum=0;
    for (int i=0; i<count; i++) {
        int len = str.length();
        for (int j=0; j<len; j++) {
            if (str.charAt(j) == 'b')
                sum = sum + 1;
        }
    }
    t = System.currentTimeMillis()-t;
    System.out.println("result: "+ sum + " after " + t + "msec");

이를위한 몇 가지 전용 클래스가 있습니다.

import java.text.*;

final CharacterIterator it = new StringCharacterIterator(s);
for(char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
   // process c
   ...
}

당신이 가지고 있다면 구아바 ClassPath에서 다음은 매우 읽기 쉬운 대안입니다. Guava는이 경우에 대해 상당히 현명한 사용자 정의 목록 구현을 가지고 있으므로 비효율적이지 않아야합니다.

for(char c : Lists.charactersOf(yourString)) {
    // Do whatever you want     
}

업데이트 : @alex가 지적했듯이 Java 8과 함께도 있습니다. CharSequence#chars 사용. 유형조차도 intstream이므로 다음과 같은 숯에 매핑 할 수 있습니다.

yourString.chars()
        .mapToObj(c -> Character.valueOf((char) c))
        .forEach(c -> System.out.println(c)); // Or whatever you want

Java8 우리는 그것을 해결할 수 있습니다:

String str = "xyz";
str.chars().forEachOrdered(i -> System.out.print((char)i));
str.codePoints().forEachOrdered(i -> System.out.print((char)i));

방법은 문자()반환합니다 IntStream 에서 언급했듯이 doc:

스트림을 반환합니다 int 제로 확장하는 문자 값에서 이 시퀀스입니다.모든 문자는 매핑드 대리점은 전달 을 통해 해석되지 않은.는 경우에는 순서가 변화하는 동안 스트림 읽는 것,결과는 정의되지 않습니다.

방법 codePoints() 또한 반환합니다 IntStream 당 doc:

스트림을 반환합니다드점의 값이다.모 대리 쌍에서 발생하는 순으로 결합에 의한 경우 문자입니다.toCodePoint 및 결과 전달됩니다.모 다른 코드 단위를 포함,일반 BMP 문자,짝이 없는 대리고,정의되지 않은 코드 단위로 확장을 int 값 는 다음을 전달됩니다.

는 방법은 문자 및 코드에 지점이 다른가요? 에서 언급했듯이 기사:

유니코드 3.1 추가 보완 문자,총을 가져 문자 보다는 더 많은 것 216 수 있는 문자 수 에 의해 구별된 하나의 16 비트 char.따라서, char 값없 더 이상은 하나를 매핑하는 기본적인 의미에서 단위 유니코드입니다.JDK5 업데이트를 지원하는 더 큰 세트의 문자 값이 있습니다.을 변경하는 대신 정의 char 유형의 일부를 새로 보충 자에 의해 표현되는 대리 쌍 의 두 개의 char 값이 있습니다.을 줄이는 이름의 혼란,코드 point 을 참조하는 데 사용되는 횟수를 나타내는 특정 유니코드 문자를 포함하여 보충 것들입니다.

마지막으로 이유 forEachOrderedforEach ?

의 행동 forEach 은 명시적으로 비결정적인 곳으로 forEachOrdered 수행 활동의 각 요소에 대한 이 스트림에서 가 발생기의 스트림 으면 스트림에 정의된가 발생할 순서입니다.그래서 forEach 을 보장하지 않는 주문이 되지 않습니다.또한 이 질문 니다.

차이 문자 코드점,문자 및 기소질문.

코드 포인트를 반복 해야하는 경우 String (이것 좀 봐 대답) 더 짧거나 읽기 쉬운 방법은 CharSequence#codePoints Java 8에 추가 된 방법 :

for(int c : string.codePoints().toArray()){
    ...
}

또는 루프 대신 스트림을 직접 사용합니다.

string.codePoints().forEach(c -> ...);

도 있습니다 CharSequence#chars 캐릭터의 스트림을 원한다면 ( IntStream, 없기 때문에 CharStream).

나는 사용하지 않을 것이다 StringTokenizer JDK의 클래스 중 하나이므로 유산입니다.

Javadoc의 말 :

StringTokenizer 새로운 코드에서 사용이 권장되지만 호환성 이유로 유지되는 레거시 클래스입니다. 이 기능을 원하는 사람은 누구나 분할 방법을 사용하는 것이 좋습니다. String 아니면 그 java.util.regex 대신 패키지.

성능이 필요하다면, 당신은 당신입니다 테스트해야합니다 당신의 환경에서. 다른 방법은 없습니다.

여기에 예제 코드 :

int tmp = 0;
String s = new String(new byte[64*1024]);
{
    long st = System.nanoTime();
    for(int i = 0, n = s.length(); i < n; i++) {
        tmp += s.charAt(i);
    }
    st = System.nanoTime() - st;
    System.out.println("1 " + st);
}

{
    long st = System.nanoTime();
    char[] ch = s.toCharArray();
    for(int i = 0, n = ch.length; i < n; i++) {
        tmp += ch[i];
    }
    st = System.nanoTime() - st;
    System.out.println("2 " + st);
}
{
    long st = System.nanoTime();
    for(char c : s.toCharArray()) {
        tmp += c;
    }
    st = System.nanoTime() - st;
    System.out.println("3 " + st);
}
System.out.println("" + tmp);

Java 온라인 나는 얻다:

1 10349420
2 526130
3 484200
0

Android x86 API 17에서 나는 얻는다 :

1 9122107
2 13486911
3 12700778
0

보다 Java 튜토리얼 : 문자열.

public class StringDemo {
    public static void main(String[] args) {
        String palindrome = "Dot saw I was Tod";
        int len = palindrome.length();
        char[] tempCharArray = new char[len];
        char[] charArray = new char[len];

        // put original string in an array of chars
        for (int i = 0; i < len; i++) {
            tempCharArray[i] = palindrome.charAt(i);
        } 

        // reverse array of chars
        for (int j = 0; j < len; j++) {
            charArray[j] = tempCharArray[len - 1 - j];
        }

        String reversePalindrome =  new String(charArray);
        System.out.println(reversePalindrome);
    }
}

길이를 넣으십시오 int len 그리고 사용 for 고리.

StringTokenizer는 문자열을 개별 문자로 나누는 작업에 완전히 적합하지 않습니다. 와 함께 String#split() 예를 들어 아무것도 일치하지 않는 정규식을 사용하여 쉽게 할 수 있습니다.

String[] theChars = str.split("|");

그러나 StringTokenizer는 Regexes를 사용하지 않으며 문자간에 아무것도 일치하지 않는 구분 기자 문자열이 없습니다. 거기 ~이다 하나의 귀여운 작은 핵은 같은 것을 달성하는 데 사용할 수 있습니다. 문자열 자체를 구분 기자 문자열로 사용하고 (모든 문자를 구분 기자로 만들고) 구분 장치를 반환하도록하십시오.

StringTokenizer st = new StringTokenizer(str, str, true);

그러나 나는이 옵션들을 해고 할 목적으로만 언급합니다. 두 기술 모두 원래 문자열을 문자 프리미티브 대신 1 차 문자열로 나누고, 둘 다 객체 생성 및 문자열 조작의 형태로 많은 오버 헤드를 포함합니다. 그것을 루프로 charat ()를 호출하는 것과 비교하여 사실상 오버 헤드가 발생하지 않습니다.

정교함 이 답변 그리고 이 답변.

위의 답변은 코드 포인트 값으로 반복하지 않는 많은 솔루션의 문제를 지적합니다. 대리 문자. Java Docs 도이 문제를 설명합니다 여기 ( "유니 코드 문자 표현"참조). 어쨌든, 여기에는 보충 유니 코드 세트에서 실제 대리 문자를 사용하고 변환하는 코드가 있습니다. 문자열로. .tochars ()는 숯불 배열을 반환합니다. 대리를 다루는 경우 반드시 두 숯이 있습니다. 이 코드는 작동해야합니다 어느 유니 코드 문자.

    String supplementary = "Some Supplementary: 𠜎𠜱𠝹𠱓";
    supplementary.codePoints().forEach(cp -> 
            System.out.print(new String(Character.toChars(cp))));

이 예제 코드가 도움이 될 것입니다!

import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class Solution {
    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<String, Integer>();
        map.put("a", 10);
        map.put("b", 30);
        map.put("c", 50);
        map.put("d", 40);
        map.put("e", 20);
        System.out.println(map);

        Map sortedMap = sortByValue(map);
        System.out.println(sortedMap);
    }

    public static Map sortByValue(Map unsortedMap) {
        Map sortedMap = new TreeMap(new ValueComparator(unsortedMap));
        sortedMap.putAll(unsortedMap);
        return sortedMap;
    }

}

class ValueComparator implements Comparator {
    Map map;

    public ValueComparator(Map map) {
        this.map = map;
    }

    public int compare(Object keyA, Object keyB) {
        Comparable valueA = (Comparable) map.get(keyA);
        Comparable valueB = (Comparable) map.get(keyB);
        return valueB.compareTo(valueA);
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top