読み込み中...

Kotlinでリスト操作しよう!たったの15選で完璧にマスター

KotlinのlistOf関数を使用したコード例のイラスト Kotlin
この記事は約21分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

本記事のサンプルコードを活用して機能追加、目的を達成できるように作ってありますので、是非ご活用ください。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を満たす現役のプログラマチームによって監修されています。

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

プログラミングの世界には多様な言語と無限の可能性が広がっています。

特にKotlinは、その簡潔さと効率性から多くの開発者に愛されています。

この記事を読めば、Kotlinでのリスト操作を完璧にマスターすることができるようになります。

リスト操作はデータの管理と処理において不可欠なスキルです。

それでは、一緒にKotlinの魅力を深掘りし、listOf関数の使い方を学んでいきましょう。

●Kotlinとは

KotlinはJetBrainsによって開発された静的型付けのプログラミング言語です。

Javaとの相互運用性、簡潔な構文、Null安全など、多くの特徴を持っており、Androidアプリ開発をはじめとする多くのフィールドで利用されています。

○Kotlinの特徴

Kotlinの大きな特徴は、Javaと100%の相互運用性があることです。

Javaのライブラリやフレームワークをそのまま利用でき、JavaコードをKotlinコードに簡単に変換することも可能です。

さらに、KotlinはNull安全をサポートしており、Null参照によるランタイムエラーを大幅に削減することができます。

もう一つの特徴は、簡潔で読みやすいコードが書けることです。

Kotlinは、冗長なコードを減らし、より直感的で理解しやすいコードを書くための工夫がなされています。

これにより、開発者はより効率的に、安全なコードを書くことができます。

Kotlinは、コンパイルが速く、実行速度も速いため、大規模なプロジェクトでもスムーズに開発を進めることができます。

また、Kotlinはマルチプラットフォーム対応しており、JVM、Android、iOS、JavaScript、Nativeなど、幅広いプラットフォームでの開発が可能です。

●listOf関数の基本

Kotlinの中で、リスト操作には多くの関数が提供されていますが、その中でも基本的で非常に有用なのが「listOf」関数です。

この関数を使うことで、様々な要素を持つリストを簡単に生成できます。

○listOfの定義と特徴

「listOf」は、Kotlinの標準ライブラリの一部として提供されている関数です。

この関数を使用することで、簡単にリストを作成することができます。

生成されるリストはデフォルトでImmutable(変更不可)です。したがって、一度作成されたリストの要素を後から変更することはできません。

下記のサンプルコードは、listOf関数を使ってリストを生成する基本的な例を表しています。

val fruits = listOf("りんご", "ばなな", "みかん")
println(fruits)

このコードでは、3つのフルーツの名前を要素として持つリストを作成しています。

リストを実行すると、次のような結果を得られます。

りんご, ばなな, みかん

このリストはImmutableなので、要素を追加したり削除したりすることはできません。

もし要素の追加や削除を行いたい場合は、MutableListを使用する必要があります。

●listOfの使い方

Kotlinでリストを操作する際の基本となるのが「listOf」関数です。

この関数を駆使することで、様々なリスト操作が可能となります。

ここでは、その基本的な使い方をサンプルコードを交えて詳しく解説します。

○サンプルコード1:基本的なリストの作成

Kotlinでの最もシンプルなリストの作成方法を紹介します。

下記のサンプルコードは、3つのフルーツの名前を要素として持つリストを作成しています。

val fruits = listOf("りんご", "ばなな", "みかん")
println(fruits) // [りんご, ばなな, みかん]

このコードを実行すると、リストに格納されたフルーツの名前が順に表示されます。

こちらのリストは変更不可能なので、一度定義すると要素の追加や削除はできません。

○サンプルコード2:異なるデータ型の要素を持つリストの作成

Kotlinでは、異なるデータ型の要素を持つリストも作成できます。

例として、整数、浮動小数点数、文字列を要素として持つリストを作成してみましょう。

val mixedList = listOf(1, 2.5, "文字列")
println(mixedList) // [1, 2.5, 文字列]

このコードでは、Int、Double、Stringという3つの異なるデータ型の要素をリストに格納しています。

KotlinのlistOf関数は型推論を行い、異なるデータ型の要素も問題なくリストに格納します。

○サンプルコード3:変更可能なMutableListの作成

Kotlinで扱うリストは、基本的に不変(Immutable)です。

しかし、場面によってはリストの内容を変更したいことがあります。

その際に使用するのが「MutableList」です。

MutableListを使うことで、リストの要素の追加や削除、変更が可能となります。

具体的なコードを見てみましょう。

// MutableListの作成
val numbers = mutableListOf(1, 2, 3)
println(numbers) // [1, 2, 3]

// 要素の追加
numbers.add(4)
println(numbers) // [1, 2, 3, 4]

// 要素の削除
numbers.removeAt(1)
println(numbers) // [1, 3, 4]

このコードでは、まず3つの整数を要素として持つMutableListを作成しています。

その後、addメソッドを使用して新しい要素を追加し、removeAtメソッドを使用して要素を削除しています。

結果として、リストは[1, 3, 4]という状態に変わっています。

○サンプルコード4:リストの要素にアクセスする方法

リストに格納されている要素へのアクセスは、インデックス番号を指定することで行えます。

インデックスは0から始まることを注意しましょう。

val fruits = listOf("りんご", "ばなな", "みかん")

// インデックスで要素にアクセス
val firstFruit = fruits[0]
println(firstFruit) // りんご

このコードでは、fruitsリストの0番目の要素(”りんご”)を取得しています。

Kotlinでは、リストの要素に直接インデックスを使用してアクセスすることが可能です。

○サンプルコード5:リストの要素を変更する方法

前述の通り、不変のリストでは要素の変更はできませんが、MutableListを使用することで要素の変更が可能となります。

val colors = mutableListOf("赤", "青", "緑")

// 要素の変更
colors[1] = "黄"
println(colors) // [赤, 黄, 緑]

このコードでは、初めに”赤”、”青”、”緑”という3つの要素を持つMutableListを作成しています。

その後、1番目の要素を”黄”に変更しています。

●listOfの応用例

KotlinのlistOf関数は非常に柔軟であり、基本的なリスト操作だけでなく、さまざまな応用的な操作もサポートしています。

ここでは、listOfを用いたリスト操作の応用例をいくつか紹介します。

○サンプルコード6:リストのフィルタリング

リストから特定の条件を満たす要素だけを取り出す場合、filter関数を使用します。

val numbers = listOf(1, 2, 3, 4, 5)
// 偶数だけを取り出す
val evenNumbers = numbers.filter { it % 2 == 0 }
println(evenNumbers) // [2, 4]

このコードでは、リストから偶数のみを取り出しています。

filter関数内の{ it % 2 == 0 }という部分が偶数を取得する条件となります。

○サンプルコード7:リストのマッピング

リストの各要素を変換したい場合、map関数を利用します。

val words = listOf("apple", "banana", "cherry")
// 各要素の文字数を取得
val lengths = words.map { it.length }
println(lengths) // [5, 6, 6]

このコードは、フルーツの名前のリストから、それぞれの名前の文字数を新たなリストとして取得しています。

map関数内の{ it.length }という部分が各要素を文字数に変換する操作を示しています。

これらの関数を組み合わせることで、より複雑なリスト操作も行うことができます。

例えば、偶数だけを取り出して、それらの数値を二乗した新しいリストを作成するといった操作も可能です。

○サンプルコード8:リストのソート

Kotlinにおけるリストの要素をソートする際は、sorted関数やsortedBy関数を使用します。

これにより、昇順や降順、特定の条件に基づいてソートを行うことができます。

val unsortedNumbers = listOf(5, 2, 8, 1, 3)
// 昇順にソート
val sortedNumbers = unsortedNumbers.sorted()
println(sortedNumbers) // [1, 2, 3, 5, 8]

上のコードでは、数字のリストを昇順にソートしています。

sorted関数はデフォルトで昇順に要素を並べ替えます。

もし、特定の条件でソートしたい場合は、sortedBy関数を使用します。

val fruits = listOf("apple", "banana", "cherry", "blueberry")
// 文字数に基づいてソート
val sortedByLength = fruits.sortedBy { it.length }
println(sortedByLength) // [apple, cherry, banana, blueberry]

こちらのコードでは、文字列のリストを、その文字数に基づいてソートしています。

sortedBy関数内の{ it.length }という部分がソートの基準を示しています。

○サンプルコード9:リストの集約

リストの要素を集約して、1つの値にまとめる際には、reducefoldといった関数を利用します。

val numbers = listOf(1, 2, 3, 4, 5)
// すべての要素の合計を取得
val sum = numbers.reduce { acc, n -> acc + n }
println(sum) // 15

上記のコードでは、数字のリストの全ての要素を合計しています。

reduce関数を使用し、{ acc, n -> acc + n }という部分で加算を行っています。

ここで、accは累積値、nは現在の要素を表しています。

○サンプルコード10:リストの連結

Kotlinでは、複数のリストを連結することが頻繁に必要となります。

これは、特定の操作を行った結果を結合する際や、異なるデータソースからのデータを1つのリストとして取り扱う際などに役立ちます。

Kotlinでのリストの連結は、plus演算子やunion関数を使って行うことができます。

まず、plus演算子を使用した方法を見てみましょう。

val list1 = listOf("apple", "banana", "cherry")
val list2 = listOf("date", "elderberry")
val combinedList = list1 + list2
println(combinedList) // [apple, banana, cherry, date, elderberry]

上記のコードで、list1list2という2つのリストを連結して、新しいリストcombinedListを作成しています。

このcombinedListには、両方のリストの要素が順番に含まれます。

次に、union関数を使用した方法を考えます。

この関数は、2つのリストを結合するだけでなく、重複する要素を削除するという特徴があります。

val listA = listOf(1, 2, 3, 4, 5)
val listB = listOf(4, 5, 6, 7, 8)
val mergedList = listA.union(listB)
println(mergedList) // [1, 2, 3, 4, 5, 6, 7, 8]

上記のコードでは、listAlistBには4と5という重複する要素がありますが、union関数により、連結後のmergedListには重複する要素は1つだけとなっています。

これらの方法を使用することで、Kotlinで簡単にリストを連結することができます。

また、状況に応じて重複する要素を削除することも可能です。

○サンプルコード11:リストの分割

リストの分割は、特定の条件に基づいてリストを複数の部分リストに分割することを指します。

Kotlinでは、chunkedwindowedなどの関数を使用して、このような操作を簡単に行うことができます。

chunked関数を使用すると、リストを指定したサイズの部分リストに分割することができます。

val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
val chunkedList = numbers.chunked(3)
println(chunkedList) // [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

このコードでは、数字のリストを3つの要素ごとに分割しています。

その結果、3つの部分リストを持つ新しいリストchunkedListが作成されます。

○サンプルコード12:リストの要素の削除

Kotlinにおいて、リストから特定の要素を削除する場面は頻繁に発生します。

Kotlinのリストには、特定の条件に基づいて要素を取り除くためのメソッドが豊富に提供されており、その中でも特に使いやすいものをいくつか紹介します。

  1. filter関数を使用して、特定の条件を満たす要素だけを新しいリストとして取得する方法です。
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
val evenNumbers = numbers.filter { it % 2 == 0 }
println(evenNumbers) // 出力結果は[2, 4, 6, 8]となります。

上記のコードでは、偶数のみを新しいリストとして取得しています。

ここでのポイントは、元のリストnumbersは変更されていない点です。

  1. removeIf関数を利用した方法。この方法は、MutableListに対してのみ利用可能です。
val fruits = mutableListOf("apple", "banana", "cherry", "date")
fruits.removeIf { it.startsWith("b") }
println(fruits) // 出力結果は["apple", "cherry", "date"]となります。

このコードの実行結果、fruitsリストから”banana”という要素が削除されることが確認できます。

  1. minus演算子を使用して、特定の要素を取り除く方法もあります。
val languages = listOf("Kotlin", "Java", "C++", "Python")
val withoutJava = languages - "Java"
println(withoutJava) // 出力結果は["Kotlin", "C++", "Python"]となります。

このコードでは、”Java”という要素が新しいリストから除外されていることがわかります。

○サンプルコード13:リストと配列の相互変換

Kotlinでは、リストと配列の間で簡単にデータの変換を行うことができます。

この変換機能は、Javaとの連携や、特定のライブラリでのデータ操作を行う際など、さまざまなシーンで役立ちます。

リストを配列に変換する際は、toTypedArray関数を使用します。

val numberList = listOf(1, 2, 3, 4, 5)
val numberArray = numberList.toTypedArray()
println(numberArray.joinToString()) // 出力結果は"1, 2, 3, 4, 5"となります。

逆に、配列をリストに変換する場合は、asList関数を使用します。

val colorArray = arrayOf("red", "green", "blue")
val colorList = colorArray.asList()
println(colorList) // 出力結果は["red", "green", "blue"]となります。

このコードを実行すると、配列colorArrayがリストcolorListに変換されることが確認できます。

このように、Kotlinではリストと配列の間の変換がスムーズに行えます。

○サンプルコード14:リストのコピー

Kotlinでリストを効率的にコピーする方法を学ぶことは、データ操作の際のバグを防ぐために非常に重要です。

特に、元のリストのデータを変更せずに新しいリストを作成したい場合には、この知識は必須となります。

  1. シャローコピー:toList関数

toList関数を使用すると、元のリストの要素の参照を持つ新しいリストを作成することができます。

しかし、この方法では深いコピーは作成されません。

val originalList = listOf("apple", "banana", "cherry")
val copiedList = originalList.toList()
println(copiedList)  // 出力結果は["apple", "banana", "cherry"]です。

このコードを実行すると、新しいリストcopiedListが作成されますが、このリストの要素はoriginalListの要素と同じです。

  1. ディープコピー:map関数

map関数を使用すると、元のリストの各要素を元に新しい要素を生成し、それを含む新しいリストを作成することができます。

data class Fruit(val name: String)
val originalFruits = listOf(Fruit("apple"), Fruit("banana"), Fruit("cherry"))
val copiedFruits = originalFruits.map { Fruit(it.name) }
println(copiedFruits)  // 出力結果は[Fruit(name=apple), Fruit(name=banana), Fruit(name=cherry)]です。

このコードを実行すると、元のリストの要素とは異なる新しい要素を持つリストcopiedFruitsが作成されます。

○サンプルコード15:リストの比較

Kotlinでは、2つのリストが同じ要素を持つかどうかを簡単に比較することができます。

この比較は、リストの要素の順序も考慮に入れて行われます。

val list1 = listOf("a", "b", "c")
val list2 = listOf("a", "b", "c")
val list3 = listOf("c", "b", "a")

println(list1 == list2)  // 出力結果はtrueです。
println(list1 == list3)  // 出力結果はfalseです。

このコードの実行結果、list1list2は同じ要素の順序で構成されているため、結果はtrueになります。

一方、list1list3は異なる順序で要素が構成されているため、結果はfalseになります。

●注意点と対処法

Kotlinのリスト操作には、数々の利点がありますが、効果的に使用するためにはいくつかの注意点とそれに対する対処法を知っておく必要があります。

これにより、プログラミング時のトラブルを未然に防ぎ、より効果的なコードを書くことができます。

○ImmutableとMutableの違い

Kotlinでのリストには、主に二つのタイプがあります。

一つは変更不可能なList、もう一つは変更可能なMutableListです。

Listは一度作成するとその後要素の追加や削除ができないため、安全性が高いとされます。

一方、MutableListは要素の追加や削除が可能ですが、それによって不注意でデータが変更されるリスクが伴います。

val immutableList = listOf(1, 2, 3)
// immutableList.add(4)  // コンパイルエラー

val mutableList = mutableListOf(1, 2, 3)
mutableList.add(4)  // 問題なく実行されます。

上記のコードで、immutableListは要素の追加を試みるとコンパイルエラーとなります。

一方、mutableListは新しい要素の追加が可能です。

○リスト操作時のパフォーマンスに関する注意点

大きなリストの操作、特に要素の追加や削除を繰り返す場合、パフォーマンスの低下が考えられます。

これは、内部での要素の移動や再配置が頻繁に行われるためです。

このようなケースでは、適切なデータ構造の選択や、必要な操作を一度にまとめて行うことでパフォーマンスの改善を図ることが推奨されます。

val largeList = (1..100000).toMutableList()

// 複数の要素をまとめて追加する場合
largeList.addAll(listOf(100001, 100002, 100003))

このコードを実行すると、largeListに一度に複数の要素が追加されます。

これにより、要素の再配置や移動の回数を減らし、効率的な操作が可能となります。

○リストの大きさに関する注意点

リストのサイズが非常に大きくなる場合、メモリの使用量やアクセス速度に影響が出る可能性があります。

特に、リストの要素が複雑なオブジェクトである場合、メモリの使用量が急増するリスクが考えられます。

このような状況を回避するためには、リストのサイズを適切に管理し、不要な要素は定期的に削除するなどの対策を行うことが求められます。

val items = mutableListOf<String>()
for (i in 1..100) {
    items.add("item $i")
}

// リストのサイズが50を超えた場合、先頭から要素を削除
if (items.size > 50) {
    items.subList(0, items.size - 50).clear()
}

上記のコードでは、リストのサイズが50を超えると、先頭から不要な要素を削除しています。

これにより、リストのサイズを一定以下に保つことができます。

●カスタマイズ方法

Kotlinのリスト操作をさらに高度に行いたい場合、カスタマイズの方法を知っておくと非常に役立ちます。

ここでは、Kotlinの強力なカスタマイズ機能を利用して、リスト操作をより便利に、また効率的にするためのテクニックをいくつか紹介します。

○カスタム拡張関数の作成方法

Kotlinでは、既存のクラスに新しいメソッドを追加することができる拡張関数という機能が提供されています。

これを利用して、リストに特定の操作を追加することが可能です。

例えば、リスト内の偶数だけを取得する拡張関数を作成したい場合、次のように記述できます。

fun List<Int>.filterEven(): List<Int> {
    return this.filter { it % 2 == 0 }
}

上記のコードでは、リストから偶数だけをフィルタリングして新しいリストを返すfilterEvenという拡張関数を定義しています。

この拡張関数を利用することで、任意の整数リストから偶数だけを簡単に取得できます。

val numbers = listOf(1, 2, 3, 4, 5, 6)
val evenNumbers = numbers.filterEven()
println(evenNumbers)  // [2, 4, 6] と出力されます。

○データクラスとリストの相互変換のカスタマイズ

Kotlinでは、データクラスを用いてデータを効果的に扱うことができます。

これを利用して、データクラスとリストの相互変換をカスタマイズすることができます。

例えば、次のようなデータクラスがあるとします。

data class Person(val name: String, val age: Int)

このデータクラスをリストに変換するための拡張関数を定義することができます。

fun List<Person>.toNameList(): List<String> {
    return this.map { it.name }
}

このコードでは、Personのリストから名前だけを取り出して新しい文字列リストを返すtoNameListという拡張関数を定義しています。

val people = listOf(Person("Taro", 25), Person("Hanako", 22))
val names = people.toNameList()
println(names)  // [Taro, Hanako] と出力されます。

まとめ

Kotlinのリスト操作は、初心者から上級者まで幅広く使える非常に強力な機能です。

基本的な操作から応用、カスタマイズ方法まで、多くの側面からリスト操作を解説しました。

この知識を活用すれば、Kotlinでのプログラミングがさらに便利で効率的になるでしょう。

特に、カスタム拡張関数やデータクラスを駆使することで、コードの再利用性や読みやすさが大幅に向上します。

これにより、バグの少ない安定したプログラムを効率的に開発することが可能となります。

また、Kotlinでのリスト操作を深く学ぶことは、他のプログラミング言語やフレームワークへの適応もスムーズになるでしょう。

多くの言語やフレームワークにはリストやコレクションを操作する機能が備わっており、Kotlinでの経験は他の環境でも大いに役立ちます。

最後に、技術は日々進化しています。

Kotlinもまた、新しいバージョンがリリースされるたびに新機能が追加されています。

常に最新の情報を追い求め、学び続けることで、より高度なリスト操作を身につけることができるでしょう。

このガイドが、あなたのKotlinでのリスト操作の旅の一助となることを心より願っています。