How do you return an Iterator in Scala?

后端 未结 3 1387
执念已碎
执念已碎 2020-12-30 00:39

What must I do in order to be able to return an Iterator from a method/class ? How would one add that trait to a class?

3条回答
  •  孤城傲影
    2020-12-30 01:21

    These two answers had help from the posts below and thanks @Dima.

    • How do I implement an iterator for an existing singly linked list?

    • why does this iterable implementation produce a stackoverflow?

    Lets assume you have a class linked list. And the requirement is to print all the elements in the list.

    trait LinkedList {
      def nodeValue: Int
      def tailList: LinkedList
    }
    
    class Node(val nodeValue: Int, val tailList: LinkedList) extends LinkedList
    
    object Nil extends LinkedList {
      def nodeValue = throw new IllegalAccessException("head of Nil")
      def tailList = throw new IllegalAccessException("tail of Nil")
    }
    
    val singleLinkedList = new Node(1,Nil)
    val chainedLinkedList = new Node(2,singleLinkedList)
    print(chainedLinkedList)
    A$A44$A$A44$Node@7b7a2c78res0: Unit = ()
    

    Now Lets implement iterator to this class.

    trait LinkedList extends Iterator[Int]{
      def nodeValue: Int
      def tailList: LinkedList
    }
    
    class Node(val nodeValue: Int, val tailList: LinkedList) extends LinkedList {
      var ptr: LinkedList = this
    
      //The following two are mandatory for extending Iterator
      override def hasNext: Boolean = ptr match { case Nil => false; case _=> true}
    
      override def next(): Int = {
        val result = ptr.nodeValue
        ptr = ptr.tailList
        result
      }
    }
    
    object Nil extends LinkedList {
      def nodeValue = throw new IllegalAccessException("head of Nil")
      def tailList = throw new IllegalAccessException("tail of Nil")
    
      //The following two are mandatory for extending Iterator
      override def hasNext: Boolean = false
      override def next(): Int = throw new IllegalAccessException("next of Nil")
    }
    
    val singleLinkedList = new Node(1,Nil)
    val chainedLinkedList = new Node(2,singleLinkedList)
    
    //Printing this first Time
    chainedLinkedList.foreach(println)
    //Prints 2 1
    
    //Printing second Time
    chainedLinkedList.foreach(println)
    //No output
    

    In the iterator implementation, once ptr reached the end, it could did not advance back. Iterable implementation solves this.

    trait LinkedList extends Iterable[Int]{
      val nodeValue: Int
      val tailList: LinkedList
      override def toString(): String = this.mkString(" -> ")
    }
    
    class Node(val nodeValue: Int, val tailList: LinkedList) extends LinkedList {
    
      override def iterator: Iterator[Int] = Iterator
        .iterate(this: LinkedList)(_.tailList)
        .takeWhile(_ != Nil)
        .map(_.nodeValue)
    }
    
    object Nil extends LinkedList {
      lazy val nodeValue= throw new IllegalAccessException("head of Nil")
      lazy val tailList = throw new IllegalAccessException("tail of Nil")
    
      override def iterator: Iterator[Int] = Iterator.empty
    }
    
    val singleLinkedList = new Node(1,Nil)
    val chainedLinkedList = new Node(2,singleLinkedList)
    
    //Printing this first Time
    chainedLinkedList.foreach(println)
    Output 2 -> 1
    chainedLinkedList.foreach(println)
    Output 2 -> 1
    

提交回复
热议问题