3

How can I use a for-comprehension that returns something I can assign to an ordered Map? This is a simplification of the code I have:

class Bar
class Foo(val name: String, val bar: Bar)
val myList: java.util.List[Foo] = ...
val result: ListMap[String, Bar] =
    for {
        foo <- myList
    } yield (foo.name, foo.bar)

I need to make sure my result is an ordered Map, in the order tuples are returned from the for-comprehension.

With the above, I get the error:

error: type mismatch;
found   : scala.collection.mutable.Buffer[(String,Bar)]
required: scala.collection.immutable.ListMap[String,Bar]
foo <- myList

This compiles:

class Bar
class Foo(val name: String, val bar: Bar)
val myList: java.util.List[Foo] = ...
val result: Predef.Map[String, Bar] =
    {
        for {
            foo <- myList
        } yield (foo.name, foo.bar)
    } toMap

but then I assume the map won't be ordered, and I need an explicit toMap call.

How can I achieve this?

Eugene Yokota
  • 94,654
  • 45
  • 215
  • 319
ebruchez
  • 7,760
  • 6
  • 29
  • 41

2 Answers2

7

The collection.breakOut is your good friend in such a case,

val result: collection.immutable.ListMap[String, Bar] = 
  myList.map{ foo => (foo.name, foo.bar) }(collection.breakOut)

If it is important to use for-comprehension expression, it will be done as follows,

val result: collection.immutable.ListMap[String, Bar] = {
  for { foo <- myList } yield (foo.name, foo.bar)
}.map(identity)(collection.breakOut)

Scala 2.8 breakOut has explained collection.breakOut very well.

Community
  • 1
  • 1
ymnk
  • 1,145
  • 7
  • 7
  • I tried with and without .map(identity) and both seem to compile fine. Is there a difference between using .map(identity) or not? – ebruchez Sep 30 '10 at 17:33
  • In the first case, ListMap will be generated from myList directly, but the latter will generate a seq from myList and then generate ListMap from it. – ymnk Oct 01 '10 at 01:34
4

You can achieve do it by using the companion object of ListMap class as followings:

class Bar
class Foo(val name: String, val bar: Bar)
val myList: java.util.List[Foo] = ...
val result = ListMap((for(foo <- myList) yield (foo.name, foo.bar)):_*)
kmizu
  • 601
  • 3
  • 6
  • Could you please explain what the appending :\_\* means? – xiaohan2012 Sep 23 '14 at 13:27
  • I case you never figured it out; It's just special syntax for saying "insert this stuff into a method that takes vargs", i.e. `public void foo(String ...)` – habitats May 31 '16 at 14:30