迭代Set而不是List时的for循环行为

时间:2014-07-20 14:03:52

标签: scala

当给出Set实例而不是List实例时,for循环的行为如何变化?

小提琴:http://scalafiddle.net/console/67ed94744426295f96268f4ac1881b46

代码:

case class Book(title: String, authors: List[String]) {}

val books = List(
  Book("Book 1", List("Author 1", "Author 2")),
  Book("Book 2", List("Author 2")),
  Book("Book 3", List("Author 3")),
  Book("Book 4", List("Author 4"))
)

def authorsWithMultipleBooks(books: Iterable[Book]) =
  for {
    b1 <- books
    b2 <- books
    if b1 != b2
    a1 <- b1.authors
    a2 <- b2.authors
    if a1 == a2
  } yield a1

println(authorsWithMultipleBooks(books))
// Output: List(Author 2, Author 2)
println(authorsWithMultipleBooks(books.toSet))
// Output: Set(Author 2)

1 个答案:

答案 0 :(得分:3)

在这两种情况下,您都会产生"Author 2"两次,但由于Set只保留每个元素的一个等值,所以第二次产生它时它不会更改该集合。

因此for循环的行为没有改变,唯一不同的是在结果集合中插入 - 作为集合 - 丢弃重复插入。

以下是进一步澄清这一想法的一个例子:

scala> val authors = List("Author 1", "Author 2", "Author 3")
authors: List[String] = List(Author 1, Author 2, Author 3)

scala> for {
     | _ <- authors
     | } yield "Author 2"
res8: List[String] = List(Author 2, Author 2, Author 2)

scala> val authorsSet = authors.toSet
authorsSet: scala.collection.immutable.Set[String] = Set(Author 1, Author 2, Author 3)

scala> for {
     | _ <- authorsSet
     | } yield "Author 2"
res10: scala.collection.immutable.Set[String] = Set(Author 2)