Skip to content

Java と Kotlin の文字列

このガイドには、Java と Kotlin で文字列に関する一般的なタスクを実行する方法の例が含まれています。 Java から Kotlin への移行や、Kotlin らしい方法でコードを記述するのに役立ちます。

文字列を結合する

Java では、次のように行います。

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

Kotlin では、変数名の前にドル記号 ($) を使用して、その変数の値を文字列に補完(補間)します。

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

${name.length} のように、複雑な式を波括弧で囲むことで、その式の値を補完することができます。 詳細は 文字列テンプレート を参照してください。

文字列を構築する

Java では、StringBuilder を使用できます。

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

Kotlin では、buildString() を使用します。これは、文字列を構築するためのロジックをラムダ引数として受け取る インライン関数 です。

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

内部的には、buildString は Java と同じ StringBuilder クラスを使用しており、ラムダ 内部の暗黙的な this を介してアクセスします。

ラムダのコーディング規約 について詳しく学ぶ。

コレクションの要素から文字列を作成する

Java では、Stream API を使用して、フィルタリング、マッピングを行い、その後要素を収集します。

java
// 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 では、Kotlin がすべての List に対して定義している joinToString() 関数を使用します。

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

Java では、区切り文字とそれに続く要素の間にスペースを入れたい場合、区切り文字に明示的にスペースを追加する必要があります。

joinToString() の使い方について詳しく学ぶ。

文字列が空白の場合にデフォルト値を設定する

Java では、三項演算子 を使用できます。

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
// Kotlin
import kotlin.random.Random

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

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

文字列の先頭と末尾の文字を置換する

Java では、replaceAll() 関数を使用できます。 この場合の replaceAll() 関数は、それぞれ ## で始まる文字列と終わる文字列を定義する正規表現 ^####$ を受け取ります。

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

Kotlin では、文字列のデリミタ ## を指定して removeSurrounding() 関数を使用します。

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

出現箇所を置換する

Java では、例えば一部のデータを難読化するために、Pattern クラスと Matcher クラスを使用できます。

java
// 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 クラスを使用します。 さらに、マルチライン文字列 を使用すると、バックスラッシュの数を減らして正規表現パターンを簡素化できます。

kotlin
fun main() {
    // Kotlin
    val regex = Regex("""\w*\d+\w*""") // マルチライン文字列
    val input = "login: Pokemon5, password: 1q2w3e4r5t"
    val replacementResult = regex.replace(input, replacement = "xxx")
    println("Initial input: '$input'")
    println("Anonymized input: '$replacementResult'")
}

文字列を分割する

Java で、ピリオド文字 (.) を使用して文字列を分割するには、エスケープ (\\) を使用する必要があります。 これは、String クラスの split() 関数が引数として正規表現を受け取るためです。

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

Kotlin では、区切り文字の可変長引数を入力パラメータとして受け取る Kotlin の split() 関数を使用します。

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

正規表現で分割する必要がある場合は、Regex をパラメータとして受け取るオーバーロードされた split() バージョンを使用してください。

部分文字列を取得する

Java では、substring() 関数を使用できます。これは、部分文字列の取得を開始する文字のインデックス(そのインデックスを含む)を受け取ります。 特定の文字の後の部分文字列を取得するには、インデックスをインクリメントする必要があります。

java
// 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() 関数を使用するため、部分文字列を取得したい文字のインデックスを計算する必要はありません。

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

さらに、文字が最後に出現した後の部分文字列を取得することもできます。

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

マルチライン文字列を使用する

Java 15 より前は、マルチライン文字列を作成する方法がいくつかありました。例えば、String クラスの join() 関数を使用する方法です。

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

Java 15 では、テキストブロック が登場しました。 1 つ注意点があります。マルチライン文字列を出力し、三重引用符が次の行にある場合、余分な空行が含まれます。

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

出力:

Java 15 multiline output

三重引用符を最後の単語と同じ行に置くと、この動作の違いはなくなります。

Kotlin では、引用符を新しい行に置いて行をフォーマットしても、出力に余分な空行は含まれません。 各行の最も左側の文字が、その行の開始位置を特定します。Java との違いは、Java はインデントを自動的にトリミングしますが、Kotlin では明示的に行う必要がある点です。

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

出力:

Kotlin multiline output

余分な空行を入れたい場合は、マルチライン文字列にその空行を明示的に追加する必要があります。

Kotlin では、trimMargin() 関数を使用してインデントをカスタマイズすることもできます。

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

マルチライン文字列 について詳しく学ぶ。

次は?

お気に入りの慣用句があれば、プルリクエストを送って共有してください。