Java와 Kotlin의 문자열

Java와 Kotlin의 문자열

이 가이드는 Java와 Kotlin에서 문자열로 하는 일반적인 작업의 예시를 담고 있어요. Java에서 Kotlin으로 마이그레이션하고, 코드를 진짜 Kotlin스럽게 작성하는 데 도움이 될 거예요.

출처: Kotlin 공식 문서

본문

문자열 연결하기

Java에서는 이렇게 할 수 있어요.

// Java
String name = "Joe";
System.out.println("Hello, " + name);
System.out.println("Your name is " + name.length() + " characters long");

Kotlin에서는 변수 이름 앞에 달러 기호($)를 써서 그 변수의 값을 문자열에 끼워 넣을 수 있어요.

fun main() {
//sampleStart
    // Kotlin
    val name = "Joe"
    println("Hello, $name")
    println("Your name is ${name.length} characters long")
//sampleEnd
}

복잡한 표현식의 값은 ${name.length}처럼 중괄호로 감싸서 끼워 넣을 수 있어요. 자세한 내용은 문자열 템플릿을 참고하세요.

문자열 만들기

Java에서는 StringBuilder를 쓸 수 있어요.

// Java
StringBuilder countDown = new StringBuilder();
for (int i = 5; i > 0; i--) {
    countDown.append(i);
    countDown.append("\n");
}
System.out.println(countDown);

Kotlin에서는 buildString()을 써요. 문자열을 구성하는 로직을 람다 인자로 받는 인라인 함수죠.

fun main() {
//sampleStart
       // Kotlin
       val countDown = buildString {
           for (i in 5 downTo 1) {
               append(i)
               appendLine()
           }
       }
       println(countDown)
//sampleEnd
}

내부적으로 buildString은 Java와 같은 StringBuilder 클래스를 사용하며, 수신자 있는 함수 리터럴 안의 암시적 this로 접근해요.

람다 코딩 관례에 대해 더 알아보세요.

컬렉션 항목에서 문자열 만들기

Java에서는 Stream API로 항목을 필터, 매핑, 수집해요.

// Java
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6);
String invertedOddNumbers = numbers
        .stream()
        .filter(it -> it % 2 != 0)
        .map(it -> -it)
        .map(Object::toString)
        .collect(Collectors.joining("; "));
System.out.println(invertedOddNumbers);

Kotlin에서는 모든 List에 대해 정의된 joinToString() 함수를 써요.

fun main() {
//sampleStart
    // Kotlin
    val numbers = listOf(1, 2, 3, 4, 5, 6)
    val invertedOddNumbers = numbers
        .filter { it % 2 != 0 }
        .joinToString(separator = ";") {"${-it}"}
    println(invertedOddNumbers)
//sampleEnd
}

Java에서는 구분자와 뒤따르는 항목 사이에 공백을 두고 싶다면 공백을 구분자에 명시적으로 추가해야 해요.

joinToString() 사용법을 더 알아보세요.

문자열이 비어 있으면 기본값 설정하기

Java에서는 삼항 연산자를 쓸 수 있어요.

// Java
public void defaultValueIfStringIsBlank() {
    String nameValue = getName();
    String name = nameValue.isBlank() ? "John Doe" : nameValue;
    System.out.println(name);
}

public String getName() {
    Random rand = new Random();
    return rand.nextBoolean() ? "" : "David";
}

Kotlin은 기본값을 인자로 받는 인라인 함수 ifBlank()를 제공해요.

// Kotlin
import kotlin.random.Random

//sampleStart
fun main() {
    val name = getName().ifBlank { "John Doe" }
    println(name)
}

fun getName(): String =
    if (Random.nextBoolean()) "" else "David"
//sampleEnd

문자열의 시작과 끝의 문자 바꾸기

Java에서는 replaceAll() 함수를 쓸 수 있어요. 이 경우 replaceAll() 함수는 각각 ##으로 시작하고 끝나는 문자열을 정의하는 정규식 ^####$를 받아요.

// Java
String input = "##place##holder##";
String result = input.replaceAll("^##|##$", "");
System.out.println(result);

Kotlin에서는 문자열 구분자 ##과 함께 removeSurrounding() 함수를 써요.

fun main() {
//sampleStart
    // Kotlin
    val input = "##place##holder##"
    val result = input.removeSurrounding("##")
    println(result)
//sampleEnd
}

발생 항목 바꾸기

Java에서는 예를 들어 어떤 데이터를 난독화하려고 PatternMatcher 클래스를 쓸 수 있어요.

// Java
String input = "login: Pokemon5, password: 1q2w3e4r5t";
Pattern pattern = Pattern.compile("\\w*\\d+\\w*");
Matcher matcher = pattern.matcher(input);
String replacementResult = matcher.replaceAll(it -> "xxx");
System.out.println("Initial input: '" + input + "'");
System.out.println("Anonymized input: '" + replacementResult + "'");

Kotlin에서는 정규식 작업을 단순화해 주는 Regex 클래스를 써요. 추가로 멀티라인 문자열을 사용하면 백슬래시 개수를 줄여 정규식 패턴을 단순화할 수 있어요.

fun main() {
//sampleStart
    // Kotlin
    val regex = Regex("""\w*\d+\w*""") // multiline string
    val input = "login: Pokemon5, password: 1q2w3e4r5t"
    val replacementResult = regex.replace(input, replacement = "xxx")
    println("Initial input: '$input'")
    println("Anonymized input: '$replacementResult'")
//sampleEnd
}

문자열 나누기

Java에서 마침표 문자(.)로 문자열을 나눌 때는 이스케이프(\\.)가 필요해요. String 클래스의 split() 함수가 인자로 정규식을 받기 때문이죠.

// Java
System.out.println(Arrays.toString("Sometimes.text.should.be.split".split("\\.")));

Kotlin에서는 입력 매개변수로 구분자 varargs를 받는 Kotlin 함수 split()을 써요.

fun main() {
//sampleStart
    // Kotlin
    println("Sometimes.text.should.be.split".split("."))
//sampleEnd
}

정규식으로 나눠야 한다면 Regex를 매개변수로 받는 오버로드된 split() 버전을 쓰세요.

부분 문자열 가져오기

Java에서는 부분 문자열을 시작할 문자(포함)의 시작 인덱스를 받는 substring() 함수를 쓸 수 있어요. 그 문자 다음의 부분 문자열을 가져오려면 인덱스를 증가시켜야 하죠.

// Java
String input = "What is the answer to the Ultimate Question of Life, the Universe, and Everything? 42";
String answer = input.substring(input.indexOf("?") + 1);
System.out.println(answer);

Kotlin에서는 substringAfter() 함수를 써서, 부분 문자열을 시작할 문자의 인덱스를 계산할 필요가 없어요.

fun main() {
//sampleStart
    // Kotlin
    val input = "What is the answer to the Ultimate Question of Life, the Universe, and Everything? 42"
    val answer = input.substringAfter("?")
    println(answer)
//sampleEnd
}

추가로 문자의 마지막 발생 이후의 부분 문자열도 가져올 수 있어요.

fun main() {
//sampleStart
    // Kotlin
    val input = "To be, or not to be, that is the question."
    val question = input.substringAfterLast(",")
    println(question)
//sampleEnd
}

멀티라인 문자열 사용하기

Java 15 이전에는 멀티라인 문자열을 만드는 여러 방법이 있었어요. 예를 들어 String 클래스의 join() 함수를 쓰는 거죠.

// Java
String lineSeparator = System.getProperty("line.separator");
String result = String.join(lineSeparator,
       "Kotlin",
       "Java");
System.out.println(result);

Java 15에서는 텍스트 블록이 등장했어요. 한 가지 기억할 점이 있어요. 멀티라인 문자열을 출력할 때 삼중 따옴표가 다음 줄에 있으면 빈 줄이 하나 더 생긴다는 거예요.

// Java
String result = """
    Kotlin
       Java
    """;
System.out.println(result);

출력은 다음과 같아요.

삼중 따옴표를 마지막 단어와 같은 줄에 두면 이 동작 차이가 사라져요.

Kotlin에서는 따옴표를 새 줄에 두고 줄을 포맷해도 출력에 빈 줄이 하나 더 생기지 않아요. 어떤 줄이든 가장 왼쪽의 문자가 그 줄의 시작을 정해요. Java와의 차이는 Java가 들여쓰기를 자동으로 제거하는 반면, Kotlin에서는 명시적으로 해줘야 한다는 점이에요.

fun main() {
//sampleStart
    // Kotlin   
    val result = """
        Kotlin
           Java 
    """.trimIndent()
    println(result)
//sampleEnd
}

출력은 다음과 같아요.

빈 줄을 하나 더 두고 싶다면 그 빈 줄을 멀티라인 문자열에 명시적으로 추가해야 해요.

Kotlin에서는 들여쓰기를 커스터마이즈하려고 trimMargin() 함수를 쓸 수도 있어요.

// Kotlin
fun main() {
    val result = """
       #  Kotlin
       #  Java
   """.trimMargin("#")
    println(result)
}

멀티라인 문자열에 대해 더 알아보세요.

다음은?

좋아하는 관용구가 있다면 풀 리퀘스트를 보내서 공유해 주세요.

더 알아보기 (Learn more)