モーダルを閉じる工作HardwareHub ロゴ画像

工作HardwareHubは、ロボット工作や電子工作に関する情報やモノが行き交うコミュニティサイトです。さらに詳しく

利用規約プライバシーポリシー に同意したうえでログインしてください。

工作HardwareHub ロゴ画像 (Laptop端末利用時)
工作HardwareHub ロゴ画像 (Mobile端末利用時)

Scala コレクション

モーダルを閉じる

ステッカーを選択してください

モーダルを閉じる

お支払い内容をご確認ください

購入商品
」ステッカーの表示権
メッセージ
料金
(税込)
決済方法
GooglePayマーク
決済プラットフォーム
確認事項

利用規約をご確認のうえお支払いください

※カード情報はGoogleアカウント内に保存されます。本サイトやStripeには保存されません

※記事の執筆者は購入者のユーザー名を知ることができます

※購入後のキャンセルはできません

作成日作成日
2016/02/17
最終更新最終更新
2021/10/07
記事区分記事区分
一般公開

相互変換

object Main {
  def main(args: Array[String]): Unit = {
    // 順序のあるコレクション
    // Traversable -> Iterable -> Seq
    //   -> List
    //   -> Array
    //   -> Buffer -> ListBuffer, ArrayBuffer
    //   -> Vector
    //   -> Stream
    val list = List(1, 2, 3)

    // マップ
    // Traversable -> Iterable -> Map
    val map = Map("a" -> 1, "b" -> 2)

    // 集合
    // Traversable -> Iterable -> Set
    val set = Set(1, 2, 3)

    // 相互変換 (マップのみタプルが絡むため特殊)

    println(map.toList) //=> List((a,1), (b,2))
    println(map.toList.toMap) //=> Map(a -> 1, b -> 2)

    println(list.toIterable) //=> List(1, 2, 3)
    println(list.toSeq) //=> List(1, 2, 3)
    println(list.toList) //=> List(1, 2, 3)
    println(list.toArray) //=> [I@35a9cc1a
    println(list.toSet) //=> Set(1, 2, 3)

    // 生成元がミュータブルであっても、結果はイミュータブルになります。
    val mapImmutable = scala.collection.mutable.Map(1 -> 10).toMap
    // mapImmutable += (2 -> 20) // エラー
  }
}

リスト

走査

object Main {
  def main(args: Array[String]): Unit = {
    val list = List(1,2,3)
    for(e <- list) {
      println(e)
    }

    list.foreach{ e =>
      println(e)
    }
  }
}

ソート

object Main {
  def main(args: Array[String]): Unit = {
    println(List(3,1,2).sorted) //=> List(1, 2, 3)
    println(List("abc", "ab").sortWith{ (x, y) => x.length < y.length }) //=> List(ab, abc)
    println(List("abc", "ab").sortBy{ _.length }) //=> List(ab, abc)
  }
}

ネストしたリストをフラット化 (または Option 型のリストの処理)

object Main {
  def main(args: Array[String]): Unit = {
    // ruby の flatten のようなものです
    println(List(List(1,2),List(3)).flatten) //=> List(1, 2, 3)

    println(List(1,2,3).flatMap { e => // とすると、
      List(e, e)
    })
    //=> List(1, 1, 2, 2, 3, 3)
    println(List(1,2,3).map { e => // これと同じ意味。
      List(e,e)
    }.flatten) // 中間 List も生成せずに高速
    //=> List(1, 1, 2, 2, 3, 3)

    // Option 型のリストから None を除外する効果
    println(List(Some("a"), Some("b"), None).flatten) //=> List(a, b)
  }
}

文字列化 (Join)

object Main {
  def main(args: Array[String]): Unit = {
    val list = List(1,2,3)
    println(list.mkString) //=> 123
    println(list.mkString("delimiter")) //=> 1delimiter2delimiter3
    println(list.mkString("pre", "delimiter", "post")) //=> pre1delimiter2delimiter3post
  }
}

集約

object Main {
  def main(args: Array[String]): Unit = {
    // ruby の inject のようなものです
    println(List("b", "c").foldLeft("a") { (l, e) =>
      l + e
    }) //=> abc ("a" は l の初期値)

    println(List("a", "b").foldRight("c") { (e, r) =>
      e + r
    }) //=> abc ("c" は r の初期値)

    // (("a" + "b") + "c")
    println(List("a", "b", "c").reduceLeft { (l, e) =>
      l + e
    }) //=> abc

    // ("a" + ("b" + "c"))
    println(List("a", "b", "c").reduceRight { (e, r) =>
      e + r
    }) //=> abc

    // リストが空 List() の場合に例外を投げたくない場合
    println(None.reduceLeftOption { (l: Any, e: Any) =>
    }) //=> None
    println(List(1,2,3).reduceRightOption { (e: Int, r: Int) =>
      e + r
    }) //=> Some(6)
  }
}

分割

object Main {
  def main(args: Array[String]): Unit = {
    // 条件式 (true/false) で二つのリストに仕分け
    println(List(-1,2,-3).partition{ _ > 0 }) //=> (List(2),List(-1, -3))

    // 式の結果で複数のリストに仕分け
    println(List(-1,2,-3).groupBy{ _ > 0 }) //=> Map(false -> List(-1, -3), true -> List(2))

    // インデックス番号 i で二つのリスト (0..i-1, i..-1) に分割
    val (listA, listB) = List("a", "b", "c").splitAt(2)
    println(listA) //=> List(a, b)
    println(listB) //=> List(c)
  }
}

Zip (タプルを利用した処理)

object Main {
  def main(args: Array[String]): Unit = {
    // ruby の each_with_index のようなものです
    List("a", "b", "c").zipWithIndex.foreach{ tuple =>
      println(tuple) //=> (a,0), (b,1), (c,2)
    }

    // 長さが一致しない場合、超過した要素は捨てられます
    val zipped = List(1,2,3,4).zip(List("a", "b", "c"))
    val unzipped = zipped.unzip
    println(zipped) //=> List((1,a), (2,b), (3,c))
    println(unzipped) //=> (List(1, 2, 3),List(a, b, c))
  }
}

集合

昔、数学 A で出会った集合です。

object Main {
  def main(args: Array[String]): Unit = {
    val set = Set(1,2,3)

    // 要素の追加
    val set2 = set + 4
    println(set2) //=> Set(1, 2, 3, 4)
    println(set2 + 4) //=> Set(1, 2, 3, 4) (重複して追加はされない)

    // 要素の削除
    println(set - 1) //=> Set(2, 3)
    println(set - 0) //=> Set(1, 2, 3) (存在しない要素を指定してもエラーにはならない)
    println(set.filter{ _ != 1 }) //=> Set(2, 3)

    // 和集合
    println(set | Set(4,5,6)) //=> Set(5, 1, 6, 2, 3, 4) ←(A ∪ B)
    println(set ++ Set(4,5,6)) // としても Set では同じ意味

    // 積集合
    println(Set(1,2) & Set(2)) //=> Set(2) ←(A ∩ B)

    // 差集合
    println(set -- Set(1)) //=> Set(2, 3)

    // 走査
    set.foreach{ e =>
      println(e) //=> 1 => 2 => 3
    }

    // 変換
    println(set.map{ _ * 2 }) //=> Set(2, 4, 6)
  }
}

マップ

他の言語の連想配列のようなものです。

object Main {
  def main(args: Array[String]): Unit = {

    val map = Map[Int, Int](1 -> 10, 2 -> 20)

    // 値の取得
    println(map.get(1)) //=> Some(10)
    println(map(2)) //=> 20 (ただし、存在しないキーを指定すると例外)
    println(map.getOrElse(0, -1)) //=> -1

    // マップはタプルのリストのようなもの
    val tuple1 = (1, 10)
    val tuple2 = (2, 20)
    val map2 = Map(tuple1, tuple2) // 1 -> 2 は (1, 2) というタプルを生成する記法
    println(map2) //=> Map(1 -> 10, 2 -> 20)

    // 要素の追加
    val map3 = map + (3 -> 30, 4 -> 40)
    println(map3) //=> Map(1 -> 10, 2 -> 20, 3 -> 30, 4 -> 40)

    // マップの連結
    println(Map(1->10) ++ Map(2->20)) //=> Map(1 -> 10, 2 -> 20)

    // 要素の削除
    println(Map(1->10, 2->20) - 1) //=> Map(2 -> 20)
    println(Map(1->10, 2->20, 3->30, 4->40) - (1,3,4)) //=> Map(2 -> 20)
    println(Map(1->10, 2->20, 3->30, 4->40) -- List(1,3,4)) //=> Map(2 -> 20)
    println(Map(1->10,2->20).filter{ case(key,value) =>
      key == 2
    }) //=> Map(2 -> 20)

    // 走査
    map.foreach{ e =>
      println(e._1 + e._2) //=> 11 => 22 (タプルのループ)
    }
    map.foreach{ case(key, value) =>
      println(key + value) // としても同じ
    }
    println(map.keys) //=> Set(1, 2)
    println(map.values) //=> MapLike(10, 20)

    // 長さ
    println(map.size) //=> 2

    // 含まれるか、空かどうか
    println(map.contains(0)) //=> false
    println(map.isEmpty) //=> false
    println(map.nonEmpty) //=> true

    // 変換 (map の map と書くと混乱する)
    println(Map(1->10, 2->20).map{ case(key,value) =>
      (key, value * 2)
    }) //=> Map(1 -> 20, 2 -> 40)
    println(Map(1->10, 2->20).map{ case(key,value) =>
      key
    }) //=> List(1, 2)

    // ソート (キーを List に変換してソート)
    val sortedKeys = map.keys.toList.sorted
    sortedKeys.foreach{ key =>
      println(map(key)) //=> 10 => 20
    }
  }
}

ストリーム

参考: 具象不変コレクションクラス

ストリーム (Stream) はリストに似ているが、要素は遅延評価される。そのため、ストリームは無限の長さをもつことができる。呼び出された要素のみが計算される。他の点においては、ストリームはリストと同じ性能特性をもつ。

object Main {
  def main(args: Array[String]): Unit = {

    // a, b, a+b, b+(a+b),...
    def fibFrom(a: Long, b: Long): Stream[Long] = {
      a #:: fibFrom(b, a + b) // ストリームの先頭への要素の追加
    }

    val fibs = fibFrom(1,1) // 無限長
    println(fibs) //=> Stream(1, ?)

    for(i <- 0 to 10) {
      println(fibs(i))
    }

    // リストでは実現できません。
    def fibFromList(a: Long, b: Long): List[Long] = {
      a +: fibFromList(b, a + b) // リストの先頭への要素の追加
    }
    // val fibsList = fibFromList(1,1) // 無限長リストは無限にメモリを必要とする
    //=> java.lang.StackOverflowError
  }
}

その他の話題

比較

コレクションの値の比較は ==!= です。Seq は順序まで一致している必要がありますが、SetMap はその必要はありません。

ミュータブルなコレクション

Scala のコレクションは要素の追加や削除を行うときは別のインスタンスを生成する、という考えのもと既定ではイミュータブルな型です。import scala.collection.mutable._ によってミュータブルなものが利用できるようになります。

// イミュータブルな型と併用する場合はここまで import するとよい
import scala.collection.mutable

object Main {
  def main(args: Array[String]): Unit = {

    // 集合
    val setMutable = mutable.Set()// 参照先は変更されるが「参照」は変更されないため val で問題ない。

    // マップ
    val mapMutable = mutable.Map[Int,Int]()
    mapMutable += (1 -> 1)
    println(mapMutable) //=> Map(1 -> 1)

    // 配列
    // val arrMutable = mutable.Array[Int]() // これは間違い
    val arrMutable = mutable.ArrayBuffer[Int]() // ArrayBuffer がミュータブルな配列

    // リスト
    // val listMutable = mutable.List[Int]() // これは間違い
    val listMutable = mutable.ListBuffer[Int]() // ListBuffer がミュータブルなリスト
  }
}
0
詳細設定を開く/閉じる
アカウント プロフィール画像 (本文下)

Scalaはいいぞ

記事の執筆者にステッカーを贈る

有益な情報に対するお礼として、またはコメント欄における質問への返答に対するお礼として、 記事の読者は、執筆者に有料のステッカーを贈ることができます。

さらに詳しく →
ステッカーを贈る コンセプト画像

Feedbacks

Feedbacks コンセプト画像

    ログインするとコメントを投稿できます。

    関連記事

    • Scala 文字列の処理
      書式指定 object Main { def main(args: Array[String]): Unit = { println("%d + %d = %d".format(1, 1, 2)) //=> 1 + 1 = 2 } } 文字列の比較 ヒアドキュメント 他の言語でいう「ヒアドキュメント」のようなものは """ で囲うことで実現できます。 object Main ...
      したくんしたくん6/18/2018に更新
      いいねアイコン画像0
    • Scala 日付に関する処理
      Date クラスを文字列にフォーマット import java.util.Date object Main { def main(args: Array[String]): Unit = { // format は Date に限らない文字列用の機能です。 println("%d-%d-%d" format (1, 1, 1)) //=> 1-1-1 printl...
      したくんしたくん6/5/2018に更新
      いいねアイコン画像0
    • 酢豚の基本的な使い方 (sbt)
      sbt は Scala および Java を主な対象としたビルドツールです。Scala Build Tool の略ではありませんが、Simple Build Tool という明示的な記述も公式ドキュメントなどには見当りません。以下 sbt の基本的な使用例をまとめます。使用した sbt のバージョンは 0.13 です。 公式ドキュメント [sbt 0.13](http://www.scala-sb...
      ねこねこ6/30/2018に更新
      いいねアイコン画像0
    • Scala 関数のサンプルコード
      「デフォルト引数」および「Unit 型を返す関数」 object HelloWorld { def main(args: Array[String]): Unit = { def myPrint(myArg: String = "default_value") = println(myArg + "!") val result = myPrint() //=> defau...
      したくんしたくん6/26/2018に更新
      いいねアイコン画像0
    • Scala 組み込みの制御構造
      if-else 条件分岐で知られる if-else は三項演算子のようにも使用されます。 object HelloWorld { def main(args: Array[String]): Unit = { val myVal = if (!args.isEmpty) args(0) else "default" println(myVal) } ...
      したくんしたくん10/7/2021に更新
      いいねアイコン画像0