Study/java

[Java] String - indexOf, lastIndexOf : 문자열 위치 찾기

 

String indexOf란?

indexOf 메서드는 문자열에서 특정 문자가 처음으로 나타나는 위치를 반환하며, 시작 위치를 지정할 수 있습니다.

 

indexOf 메서드

 

indexOf(int ch): 문자열에서 지정된 문자가 처음으로 나타나는 위치를 반환합니다. 여기서 ch는 문자에 해당하는 아스키 코드 값입니다.

indexOf(String str): 문자열에서 지정된 문자열이 처음으로 나타나는 위치를 반환합니다.

indexOf(int ch, int fromIndex): 문자열의 특정 위치에서 시작하여 지정된 문자가 처음으로 나타나는 위치를 반환합니다.

indexOf(String str, int fromIndex): 문자열의 특정 위치에서 시작하여 지정된 문자열이 처음으로 나타나는 위치를 반환합니다.

 

 

indexOf(int ch)처럼 int를 파라미터로 받거나 indexOf(String str)처럼 문자열을 파라미터로 받습니다.

그리고 두 방식 모두 int fromIndex라는 파라미터를 받기도 합니다.

indexOf(int ch, int fromIndex) / indexOf(String str, int fromIndex)

fromIndex는 어디서부터 찾을지 정해주는 변수입니다.

 

실제 사용방식은 다음과 같습니다.

String s = "abcde";
System.out.println("What is 98(b)'s location? : " + s.indexOf(98));
System.out.println("What is e's location? : " + s.indexOf("e"));
System.out.println("What is 100(d)'s location from index 2? : " + s.indexOf(100, 2));
System.out.println("What is d's location from index 5? : " + s.indexOf("d", 5));

indexOf 사용결과
indexOf 사용결과

 

첫 번째 예제에서, 98은 문자 'b'의 아스키 코드 값이며, 'b'는 인덱스 1에 있습니다.

두 번째 예제에서, 'e'는 인덱스 4에 있습니다.

세 번째 예제에서, 인덱스 2부터 시작하여 'd'를 찾으면 인덱스 3에 위치합니다.

네 번째 예제에서, 인덱스 5부터 시작하여 'd'를 찾으면 문자열의 범위를 벗어나므로 -1을 반환합니다.

 

 

int ch 변수에 대해 추가로 설명하자면 그냥 단순 정수가 아니라 아스키코드의 숫자를 의미합니다.

첫 번째 코드에서 98을 변수로 사용했는데 98은 아스키코드로 변환하면 소문자 b입니다.

그래서 소문자 b의 위치인 1을 반환합니다.

 

세 번째 코드에서는 int와 함께 fromIndex를 사용합니다.

소문자 d(100)를 찾는데 시작점은 2번째부터입니다.

실제 위치는 3번째이지만 반환값도 3입니다.

2부터 시작한다고 해서 반환값은 1이 나오는 건 아닙니다.

내부 로직에서 fromIndex부터 반복문을 도는데 fromIndex를 정해주면 반복문을 적게 돌게 됩니다.

 

예를 들어, 길이가 10만 인 문자열에서 9만 번 이상의 문자열에서 내가 찾는 문자가 있을 때

fromIndex를 9만으로 해주면 거기서부터 반복문이 시작되어 원하는 문자의 위치를 찾습니다.

10만 번 반복할 코드를 1만 번만 반복하면 됩니다.

 

 

 

 

한 가지 더 설명하자면, indexOf(int ch, int fromIndex)와 indexOf(String str, int fromIndex)는 로직이 다릅니다.

전자는 문자 1개만 찾으면 끝나기 때문에 문자 하나하나 비교해서 그 위치를 반환한다면 후자는 String을 변수로 받기 때문에 로직이 조금 더 복잡합니다.

 

indexOf 메소드의 내부 구현

indexOf 메서드는 문자열의 각 문자를 비교하여 첫 번째로 일치하는 위치를 찾습니다.

문자열을 변수로 받는 indexOf는 내부적으로 static int indexOf 메서드를 사용합니다.

 

static int indexOf(char[] source, int sourceOffset, int sourceCount,
            char[] target, int targetOffset, int targetCount,
            int fromIndex) {
    if (fromIndex >= sourceCount) {
        return (targetCount == 0 ? sourceCount : -1);
    }
    if (fromIndex < 0) {
        fromIndex = 0;
    }
    if (targetCount == 0) {
        return fromIndex;
    }

    char first = target[targetOffset];
    int max = sourceOffset + (sourceCount - targetCount);

    for (int i = sourceOffset + fromIndex; i <= max; i++) {
        /* Look for first character. */
        if (source[i] != first) {
            while (++i <= max && source[i] != first);
        }

        /* Found first character, now look at the rest of v2 */
        if (i <= max) {
            int j = i + 1;
            int end = j + targetCount - 1;
            for (int k = targetOffset + 1; j < end && source[j]
                    == target[k]; j++, k++);

            if (j == end) {
                /* Found whole string. */
                return i - sourceOffset;
            }
        }
    }
    return -1;
}

source : 기준 문자열

sourceOffset : 기준문자열의 시작점(0이 들어감)

sourceCount : 찾을 문자열의 개수(기준문자열의 길이가 들어감)

target : 찾을 문자열

targetOffset : 찾을 문자열의 시작점(0)

targetCount : 찾을 문자열의 개수(찾을 문자열의 길이)

fromIndex는 위에서 설명한 것처럼 시작점을 의미

 

찾을 문자열의 0번째 문자가 나올 때까지 기준문자열을 문자단위로 반복문을 돌립니다.

0번째 문자의 위치를 찾으면 (찾은 위치 + 1)부터 ((찾은 위치 + 1) + 찾을 문자열의 길이 - 1)보다 작고,

기준 문자열 문자와 찾을 문자열 문자가 같을 때만 반복문을 돌립니다.

int j = i + 1;
int end = j + targetCount - 1;
for (int k = targetOffset + 1; j < end && source[j] == target[k]; j++, k++);

반복문을 돌린 결과 두 문자열이 같으면 위치값을 반환합니다.

 

예시를 들자면

String s = "abcde";
System.out.println("What is bc's location from index 5? : " + s.indexOf("bc"));

"abcde"에서 "bc"를 찾는다고 합시다.

"bc"의 0번째 문자인 b를 "abcde"에서 찾는다. -> 인덱스 1에 위치

찾은 위치 + 1 = 2

((찾은 위치 + 1) + 찾을 문자열의 길이 - 1) = 2 + 2 - 1 = 3

source [2] = 'c' , target [1] = 'c'는 같으므로 1이 반환됩니다.

 

간단하게 설명하면 기준문자열(abcde)에서 찾을 문자열(bc)의 첫번째 문자가 나오는 위치를 찾아서

그 문자의 위치부터 찾을문자열 길이만큼 반복해서 전부 일치하면 위치를 반환하는 방식입니다.

 

 

 

 

 

 

lastIndexOf란?

lastIndexOf 메서드는 문자열에서 특정 문자가 마지막으로 나타나는 위치를 반환하며, 시작 위치를 지정할 수 있습니다.

 

lastIndexOf 메서드

 

lastIndexOf(int ch): 문자열에서 지정된 문자가 마지막으로 나타나는 위치를 반환합니다.

lastIndexOf(String str): 문자열에서 지정된 문자열이 마지막으로 나타나는 위치를 반환합니다.

lastIndexOf(int ch, int fromIndex): 문자열의 특정 위치에서 시작하여 지정된 문자가 마지막으로 나타나는 위치를 반환합니다.

lastIndexOf(String str, int fromIndex): 문자열의 특정 위치에서 시작하여 지정된 문자열이 마지막으로 나타나는 위치를 반환합니다.

 

 

indexOf와 로직은 같습니다.

하지만 마지막으로 나오는 위치를 반환합니다.

파라미터도 indexOf와 동일하게 int ch나 String str을 받으며, 추가로 int fromIndex를 받기도 합니다.

 

String s = "abbbba";			
System.out.println(s.lastIndexOf(97));
System.out.println(s.lastIndexOf("a"));
System.out.println(s.lastIndexOf(97, 3));
System.out.println(s.lastIndexOf("a", 5));

lastIndexOf 사용결과
lastIndexOf 사용결과

 

첫 번째 예제에서, 'a'는 인덱스 5에 마지막으로 나타납니다.

두 번째 예제에서도, 'a'는 인덱스 5에 마지막으로 나타납니다.

세 번째 예제에서는, 인덱스 3부터 시작하여 'a'를 찾으면 인덱스 0에 위치합니다.

네 번째 예제에서는, 인덱스 5부터 시작하여 'a'를 찾으면 인덱스 5에 위치합니다.

 

 

lastIndexOf는 시작점이 뒤에서부터 시작합니다.

그리고 fromIndex는 시작점인 건 같지만 lastIndexOf는 뒤에서부터 시작하기 때문에 위의 코드에서 fromIndex를 3으로 지정하게 되면 3, 2, 1, 0 순서로 위치를 찾게 됩니다.

그래서 'a'가 위치한 0이 반환됩니다.

fromIndex로부터 앞을 자르냐 뒤를 자르냐의 차이입이다.

 

 

읽으면 좋은 글

[Java] String - offsetByCodePoints

 

[Java] String - offsetByCodePoints

offsetByCodePoints 메소드는 지정된 인덱스에서 codePointOffset 코드포인트로 오프셋 된 문자열 내의 인덱스를 리턴합니다. offsetByCodePoints(int index, int codePointOffset) 공식문서상으로는 Returns the index within t

priming.tistory.com