Kotlinのdistinct・toSetで重複を削除する方法
生徒
「Kotlinでリストの中に同じ値が何回も入っている場合、それを1つずつにまとめる方法はありますか?」
先生
「ありますよ。KotlinにはdistinctとtoSetという便利な関数があって、重複を簡単に削除できます。」
生徒
「名前が似ていますが、どう違うんですか?」
先生
「distinctは順番を保ちながら重複を削除し、toSetは集合型に変換することで重複を削除します。それぞれの特徴を詳しく見ていきましょう。」
1. distinctで重複を削除する方法:順番を維持してスッキリ
Kotlinのdistinct(ディスティンクト)は、リストの中から「すでに登場した値」を自動で見つけ出し、最初に出てきた順番を崩さずに重複だけを取り除いてくれる非常に賢い関数です。
プログラミングを始めたばかりの方でもイメージしやすいように、買い物リストを例に考えてみましょう。「りんご」を2回書いてしまっても、distinctを使えば、最初に書いた位置に「りんご」を残したまま、後から書いた余計な項目だけを消してくれます。
fun main() {
// 同じ果物が混ざっているリスト(重複あり)
val shoppingList = listOf("りんご", "バナナ", "りんご", "みかん", "バナナ")
// distinctを使って重複をカット
val uniqueList = shoppingList.distinct()
println("元のリスト: $shoppingList")
println("整理後のリスト: $uniqueList")
}
元のリスト: [りんご, バナナ, りんご, みかん, バナナ]
整理後のリスト: [りんご, バナナ, みかん]
このコードのポイントは、2回目に出てきた「りんご」や「バナナ」が消えても、「りんご」が一番最初にあるという順番は変わっていない点です。リストの並び順に意味があるデータを扱うときは、このdistinctを使うのが最も安全で確実な方法といえます。
内部的な仕組みとしては、元のリストを先頭から一つずつ確認し、新しいリストにまだ入っていないものだけを追加していく処理を行っています。難しい計算を書かなくても、たった一行でデータをクリーンにできるのがKotlinの魅力ですね。
2. toSetメソッドを使って手軽に重複データを消す方法
Kotlinでリスト(データの並び)から重複した値を一気に取り除きたいとき、最もシンプルで便利な方法の一つがtoSet()という命令を使うことです。
「Set(セット)」とは、数学でいう「集合」のようなもので、「同じ値を2つ以上持つことができない」という特別なルールを持っています。そのため、リストを一度Setに変換するだけで、魔法のように重複が消えてスッキリとしたデータになります。
fun main() {
// 同じ数字が混ざっているリストを用意します
val numbers = listOf(1, 2, 2, 3, 3, 3, 4)
// toSetを使って重複をカット!
val uniqueSet = numbers.toSet()
// 結果を表示してみましょう
println(uniqueSet)
}
[1, 2, 3, 4]
この方法のポイントは、初心者の方でも直感的に書けるほど短いコードで済む点です。ただし、注意点が1つあります。toSet()を使った後のデータは「List」ではなく「Set」という別の型に変わります。
Set型は、重複を許さない代わりに「何番目のデータを取り出す」といった操作がListほど得意ではありません。また、基本的には元の順番を保持してくれますが、プログラムの意図として「順番が何より大切」という場合は、前述したdistinct()と使い分けるのがプロのコツです。
3. どっちを使う?distinctとtoSetの決定的な違い
重複したデータを取り除きたいとき、Kotlinでは主にdistinctとtoSetの2つを使います。一見同じに見えますが、「データの並び順(順序)」をどうしたいかによって、選ぶべき方法が決まります。
① distinct(順序を守る)
元のリストに並んでいた順番をそのまま維持して、重複だけを消します。画面に表示するランキングや、時系列データを扱う場合に適しています。
② toSet(集合として扱う)
「順序」という概念を捨て、ユニークな値の「集まり」に変換します。処理速度が非常に速いため、大量のデータを照合したり、データベースに保存したりする際に便利です。
【初心者向け比較サンプル】
fun main() {
// 同じ果物(重複あり)のリスト
val fruits = listOf("Apple", "Banana", "Apple", "Orange", "Banana")
// 1. distinct:並び順を維持したまま重複を消す
val distinctFruits = fruits.distinct()
println(distinctFruits) // 結果: [Apple, Banana, Orange]
// 2. toSet:重複を消して「Set(集合)」に変換する
val fruitSet = fruits.toSet()
println(fruitSet) // 結果: [Apple, Banana, Orange] ※通常は順序が維持されるが、保証はされない
}
例えば、「ユーザーが登録した順番どおりにタグを表示したい」ならdistinctが正解です。一方で、「特定のユーザーがその権限を持っているか確認するだけ」のように、順番に関係なく中身の有無だけが重要な場合はtoSetを使うのがベストプラクティスです。
4. distinctByで特定条件(キー)に基づく重複削除
Kotlinで「名前が同じなら同一人物として扱いたい」といった、特定のデータ項目(プロパティ)に注目して重複を消したい場合には、distinctByメソッドが非常に便利です。
このメソッドは、リストの中から「どの項目を基準に重複を判定するか」を自分で指定できるのが最大の特徴です。プログラミング初心者の方でも、以下のコードを見ればイメージが掴みやすいでしょう。
// ユーザー情報をまとめたデータ
data class User(val name: String, val age: Int)
fun main() {
val users = listOf(
User("田中", 20), // 田中さん(20歳)
User("田中", 25), // 田中さん(25歳)
User("佐藤", 20) // 佐藤さん(20歳)
)
// 「名前(name)」を基準にして重複を削除する
val uniqueByName = users.distinctBy { it.name }
// 結果を表示
println(uniqueByName)
}
[User(name=田中, age=20), User(name=佐藤, age=20)]
実行結果を見ると、「田中」という名前が重複していたため、リストの先頭にいた「20歳の田中さん」だけが残り、後から出てきた「25歳の田中さん」は除外されています。
このようにdistinctByを使うと、オブジェクト全体が完全に一致していなくても、IDや氏名、メールアドレスといった特定のキーだけを比較してデータを整理できるため、実務の開発現場でも頻繁に活用されるテクニックです。
5. 実用例:メールアドレスの重複排除
実際のアプリ開発やWebサービスでよくあるのが、「会員登録されたメールアドレスのリストから重複を取り除きたい」というケースです。例えば、キャンペーンの案内メールを送る際、同じ人に何度もメールが届いてしまうと迷惑ですし、配信コストも余計にかかってしまいます。
Kotlinのdistinct()を使えば、プログラミング初心者の方でも驚くほど簡単に「リストの掃除」ができます。難しいループ処理や条件分岐を自分で書く必要はありません。
fun main() {
// 1. 重複が含まれているメールアドレスのリストを作成
val emails = listOf(
"test@example.com",
"user@example.com",
"test@example.com", // 重複
"info@example.com",
"user@example.com" // 重複
)
// 2. distinct()を使って、重複したデータだけを自動で削除する
val uniqueEmails = emails.distinct()
// 3. 結果を表示して確認
println("整理後のリスト: $uniqueEmails")
println("元の件数: ${emails.size}件 -> 整理後: ${uniqueEmails.size}件")
}
整理後のリスト: [test@example.com, user@example.com, info@example.com]
元の件数: 5件 -> 整理後: 3件
このプログラムでは、リストの中にあった重複分が自動的に判断され、1つずつに集約されています。このように、無駄なデータを省いて必要なものだけを抽出することで、通知機能やデータベースへの登録といった後の処理を効率化し、システム全体のパフォーマンス向上にもつながります。
6. distinctとfilterを組み合わせた応用テクニック
Kotlinのdistinctは単体でも非常に便利ですが、他の関数と組み合わせることでさらに実用的なデータ処理が可能になります。特にfilterと組み合わせることで、条件に合うデータだけを抽出したうえで重複を削除するという処理が簡単に実現できます。
例えば特定の条件に一致するデータだけを取り出し、その中で重複をなくしたい場合に非常に役立ちます。プログラミング初心者の方でもこの組み合わせを覚えておくことで実務で使える処理の幅が一気に広がります。
fun main() {
val numbers = listOf(1, 2, 2, 3, 4, 4, 5)
// 偶数だけを抽出して重複を削除
val result = numbers.filter { it % 2 == 0 }.distinct()
println(result)
}
[2, 4]
このように条件抽出と重複削除を組み合わせることで、より実践的なデータ処理をシンプルに書くことができます。
7. toSetからListへ戻す方法
toSetを使って重複を削除したあとに、再びListとして扱いたい場面もあります。例えば順番に処理をしたい場合やインデックスでアクセスしたい場合です。
そのような場合はtoListを使うことで簡単にListへ戻すことができます。この流れを理解しておくことでデータ型の変換にも柔軟に対応できるようになります。
fun main() {
val list = listOf("A", "B", "A", "C")
// 一度Setにして重複削除
val uniqueList = list.toSet().toList()
println(uniqueList)
}
[A, B, C]
このようにtoSetとtoListを組み合わせることで重複削除とリスト化を同時に行うことができます。
8. パフォーマンスを意識した使い分け
KotlinでdistinctとtoSetを使う際には処理速度の違いも意識するとより良いコードを書くことができます。一般的にtoSetは内部的に効率的なデータ構造を使っているため大量データの重複削除に適しています。
一方でdistinctは順番を維持するための処理が入るため少しコストがかかりますが、その分見た目が自然な結果になります。
つまり大量データの処理や高速処理が必要な場合はtoSet、表示や順序が重要な場合はdistinctというように目的に応じて使い分けることが重要です。
fun main() {
val data = (1..1000).toList()
val distinctData = data.distinct()
val setData = data.toSet()
println("distinct size: ${distinctData.size}")
println("set size: ${setData.size}")
}
distinct size: 1000
set size: 1000
このように結果は同じでも内部の処理が異なるため用途に応じて最適な方法を選択することが重要です。
Kotlinを基礎からしっかり学びたい人や、 Java経験を活かしてモダンな言語にステップアップしたい人には、 定番の入門書がこちらです。
基礎からわかるKotlinをAmazonで見る※ Amazon広告リンク
まとめ
Kotlinでリストの重複を削除する方法として紹介したdistinctとtoSetはどちらも非常に重要なテクニックです。プログラミング初心者の方でも理解しやすくデータ整理やデータ加工の基本として必ず覚えておきたい機能です。特に実務においてはユーザー情報や商品データやログデータなど同じ値が何度も入ってしまうケースが多くこれらを効率よく整理することが求められます。
distinctはリストの順番を維持しながら重複を削除できるため表示順序が重要な場合に最適です。例えばランキング表示や時系列データや履歴情報など順番に意味があるデータではdistinctを使うことで自然な形を保ったままデータを整理できます。一方でtoSetは集合という考え方を使い重複を取り除く方法であり順番よりもデータの一意性を重視したい場合に適しています。
またdistinctByを使うことで特定の項目を基準に重複を削除できる点も重要です。例えばユーザー名やメールアドレスなど一部の情報だけを比較してデータを整理したい場合に非常に役立ちます。このような処理はデータベース設計や業務システム開発において頻繁に使われるため理解しておくと応用の幅が広がります。
Kotlinのコレクション操作はシンプルでありながら非常に強力であり初心者でも少ないコードで高度な処理を実現できます。重複削除の処理を自分でループや条件分岐を使って書くと複雑になりやすいですがdistinctやtoSetを使えば一行で処理できるためコードの可読性や保守性が大きく向上します。
実務ではメールアドレスの重複排除や検索結果の整理やタグの重複削除などさまざまな場面で活用されます。特にデータ量が多くなると処理の効率やパフォーマンスが重要になるため適切な関数を選択することが大切です。順序を維持したいかそれとも単純に重複をなくしたいかという観点で使い分けることがポイントになります。
さらにコレクション操作を理解することで他の機能にも応用が利くようになります。例えばフィルタリングや並び替えやグループ化といった処理も同じ考え方で扱うことができます。KotlinのdistinctやtoSetはその基礎となる重要な機能でありプログラミングスキルを高めるための第一歩として最適です。
サンプルプログラムで復習
fun main() {
val list = listOf("A", "B", "A", "C", "B")
val distinctList = list.distinct()
val setData = list.toSet()
println("distinct結果: $distinctList")
println("toSet結果: $setData")
}
distinct結果: [A, B, C]
toSet結果: [A, B, C]
生徒
「distinctとtoSetの違いがよく分かりました順番が大事かどうかで使い分けるんですね」
先生
「その通りです順番を維持したいならdistinct一意性だけならtoSetを使うのが基本です」
生徒
「distinctByも便利そうですねデータの一部で比較できるのは実務で使えそうです」
先生
「はい特にユーザー管理やデータ整理では非常に重要な考え方になります」
生徒
「少ないコードで重複削除できるのはとても便利ですね」
先生
「Kotlinの強みはシンプルで読みやすいコードですこれからもコレクション操作を学んでいきましょう」
【未経験OK】Kotlinで始めるプログラミング入門|ゼロから「動く喜び」を体験する60分
「プログラミングを始めたい」を形にする。最新言語Kotlinで楽しむ、ものづくりの第一歩。
本講座は、プログラミング経験が全くない方のためのエントリー講座です。「コードを書くってどういうこと?」という基本から、世界中で使われている最新言語Kotlin(コトリン)を使って、実際にプログラムを動かすまでを体験します。難しい理屈よりも、まずは「自分の手で動かす楽しさ」を最短距離で実感していただきます。
具体的な体験内容と環境
【つくるもの】
簡単な言葉を入力すると自動で返答してくれる「対話型ミニプログラム」や、計算を自動化する「便利ツール」をゼロから作成します。黒い画面に自分の書いた文字が表示される瞬間は、最高の感動体験です。
【開発環境】
プロのエンジニアが実際に使っている開発ツールIntelliJ IDEA(インテリジェイ)をインストールします。ボタン一つで日本語化し、初心者でも迷わず操作できる「魔法の設定」を一緒に行います。
この60分で得られる3つの体験
プロと同じ道具を揃えることで、明日から一人でもプログラミングを続けられる環境が整います。
「変数」や「型」といった難しい言葉も、身近な例え話で解説。モヤモヤをゼロにします。
Kotlinは英語に近くて読みやすいのが特徴。自分でコードを読んで、間違いを見つけるコツも伝授します。
※本講座は、パソコン操作が不安な方でも安心して受講いただける完全マンツーマンです。あなたのペースに合わせて、一つずつ丁寧に進めていきます。
Kotlinで始めるプログラミング入門|ゼロから「動く喜び」を体験