メインコンテンツまでスキップ

JavaとKotlinの文字列

このガイドでは、JavaとKotlinで文字列を扱う一般的なタスクを実行する方法の例を紹介します。 これは、Javaから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() {

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

}

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

文字列の構築

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

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

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

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

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

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

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

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

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

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

Kotlinでは、文字列区切り文字##を持つremoveSurrounding()関数を使用します。

fun main() {

// Kotlin
val input = "##place##holder##"
val result = input.removeSurrounding("##")
println(result)

}

オカレンスの置換

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

// 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() {

// 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'")

}

文字列の分割

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

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

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

fun main() {

// Kotlin
println("Sometimes.text.should.be.split".split("."))

}

正規表現で分割する必要がある場合は、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() {

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

}

さらに、文字の最後のオカレンスの後に部分文字列を取得できます。

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
String lineSeparator = System.getProperty("line.separator");
String result = String.join(lineSeparator,
"Kotlin",
"Java");
System.out.println(result);

Java 15では、テキストブロックが登場しました。 覚えておくべきことが1つあります。複数行文字列を出力し、三重引用符が次の行にある場合、余分な空行ができます。

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

出力:

Java 15 multiline output

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

Kotlinでは、新しい行に引用符を付けて行をフォーマットでき、出力に余分な空行はありません。 任意の行の左端の文字は、行の先頭を識別します。Javaとの違いは、Javaが自動的にインデントをトリムするのに対し、Kotlinでは明示的に行う必要があることです。

fun main() {

// Kotlin
val result = """
Kotlin
Java
""".trimIndent()
println(result)

}

出力:

Kotlin multiline output

余分な空行が必要な場合は、この空行を複数行文字列に明示的に追加する必要があります。

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

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

複数行文字列の詳細をご覧ください。

次は何をしますか?

お気に入りのイディオムがある場合は、プルリクエストを送信して共有してください。