Почему Stream.distinct не отличается? - PullRequest
0 голосов
/ 06 ноября 2018

Я пробую следующий код и с удивлением обнаруживаю дубликаты. Я думал, что Stream.distinct будет возвращать только разные значения. Что я тут не так делаю?

import scala.collection.mutable
import scala.util.Random.shuffle

object DistinctStreamTest {
   def rand(): Stream[Int] = Stream.cons(shuffle(1 to 1000).head, rand()).distinct

   def main(args: Array[String]): Unit = {
      val usedNumbers = mutable.HashSet.empty[String]
      (0 to 100).foreach(i => {
         val newNumber = rand().take(1).mkString
         if (usedNumbers.contains(newNumber)) {
            println(s"Found duplicates: $newNumber after $i iterations")
         }
         usedNumbers += newNumber
      })
   }
}

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

Причина, по которой вы получаете дубликаты, состоит в том, что вы определили rand() как def. Это означает, что каждый вызов создает новый и отличный Stream[Int]. Вы берете только 1-й элемент из каждого нового Stream, но вероятность повторения довольно высока.

Вы могли бы исправить это, сделав вместо этого rand a val, но вы определили его рекурсивно и поэтому попытка получить доступ к чему-либо после головы вызовет бесконечную рекурсию.

Правильный способ получить случайную последовательность различных значений:

val sq :Seq[Int] = util.Random.shuffle(1 to 1000)

Затем, чтобы получить доступ к значениям, вы можете:

(0 to 100).foreach(i => {
  val newNumber = sq(i).toString()
  ... //etc.
0 голосов
/ 06 ноября 2018

Вы определили rand() как бесконечно рекурсивную Stream; поскольку оно не может быть материализовано, оно не может быть разграничено.

scala> def rand(): Stream[Int] = Stream.cons(shuffle(1 to 1000).head, rand()).distinct
rand: ()Stream[Int]

scala> rand().toList.length
java.lang.StackOverflowError
  at scala.collection.IndexedSeqLike$Elements.next(IndexedSeqLike.scala:61)
  at scala.collection.IterableLike.copyToArray(IterableLike.scala:252)
  at scala.collection.IterableLike.copyToArray$(IterableLike.scala:247)
  at scala.collection.AbstractIterable.copyToArray(Iterable.scala:54)
  at scala.collection.mutable.ArrayBuffer.$plus$plus$eq(ArrayBuffer.scala:99)
  at scala.util.Random.shuffle(Random.scala:108)

Stream s ленивы, поэтому брать вещи у них можно без потери стека.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...