LoginSignup
0
0

More than 5 years have passed since last update.

ScalaでJavaのStreamAPIを使ったら妙にハマった

Posted at

はじめに

概要

Scalaに不慣れな筆者が、JavaとScalaのListをごちゃ混ぜにしたところハマりました。普段Javaを書いていてScalaは初心者だよっていう人はハマりやすいかもと思ったので、原因と解決策をシェアします。

環境

  • Scala2.12.6
  • Java10.0.2

やりたいこと

Twitter4JのAPIで返ってくるツイートのリスト(ResponseList[Status])から必要な情報だけを抜き出して、自作クラスTweet型のListを取得したい。
JavaだとStreamAPIを使えば瞬殺できそう。

元のコード

コード

Twitter4JのAPIから返却されるResponseListはStreamAPIを使えるので、Java風に書くとこんな感じになりました。
※動きません。

val statuses: ResponseList[Status] = twitter.getUserTimeline(paging)
      val tweets: List[Tweet] = statuses
        .stream()
        .map(status => new Tweet(status.getId, status.getText, status.getUser.getName))
        .collect(Collectors.toList) //なぜかここでコンパイルエラーが…

原因

StreamAPIの終端操作.collect(Collectors.toList)で戻るのはjava.util.Listなのに、格納する変数の型がScalaのList型になっていること。

ScalaではScalaのAPIもJavaのAPIも使えますが、両者は別物。同じ名前の型を両者ともに提供していますが、ごちゃまぜに使ってはいけません。

書き直す方針

1.仕方がないのでjava.util.Listを変数の型に採用する

一番楽。

val statuses: ResponseList[Status] = twitter.getUserTimeline(paging)
val tweets: java.util.List[Tweet] = statuses
    .stream()
    .map(status => new Tweet(status.getId, status.getText, status.getUser.getName))
    .collect(Collectors.toList)

だけど、メソッドで変数tweetsを戻すなら、ScalaのListが良い!だってScalaだもの。

2.JavaのコレクションクラスをScalaのコレクションクラスに変換

Scalaのドキュメントによると、ScalaとJavaのコレクションは相互に変換できる模様。

//JavaConvertersクラスがコレクションの変換を担う
import scala.collection.JavaConverters._

val statuses: ResponseList[Status] = twitter.getUserTimeline(paging)
val tweets: List[Tweet] = statuses
      //ResponseList(Java) => mutable.Buffer(Scala)
      .asScala 
      //あとはScalaコレクション操作APIを使用
      .map(status => new Tweet(status.getId, status.getText, status.getUser.getName))
      .toList

JavaConvertersについて補足

ScalaのコレクションとJavaのコレクションの対照表

Scala Java
Iterator java.util.Iterator
Iterator java.util.Enumeration
Iterable java.lang.Iterable
Iterable java.util.Collection
mutable.Buffer java.util.List
mutable.Set java.util.Set
mutable.Map java.util.Map
mutable.ConcurrentMap java.util.concurrent.ConcurrentMap

使い方

import collection.JavaConverters._と宣言した上で、asJavaメソッドやasScalaメソッドを使うことで、変換をすることが可能。ただ、万能というわけでもないらしいので気をつけて使ってください。詳しくは公式ドキュメント

参考URL

Scala Documentation JAVAとSCALA間のコレクションの変換

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0