@@ -392,8 +392,16 @@ trait Iterator[+A] extends TraversableOnce[A] {
392
392
*/
393
393
def flatMap [B ](f : A => GenTraversableOnce [B ]): Iterator [B ] = new AbstractIterator [B ] {
394
394
private var cur : Iterator [B ] = empty
395
- def hasNext : Boolean =
396
- cur.hasNext || self.hasNext && { cur = f(self.next()).toIterator; hasNext }
395
+ private def nextCur () { cur = f(self.next()).toIterator }
396
+ def hasNext : Boolean = {
397
+ // Equivalent to cur.hasNext || self.hasNext && { nextCur(); hasNext }
398
+ // but slightly shorter bytecode (better JVM inlining!)
399
+ while (! cur.hasNext) {
400
+ if (! self.hasNext) return false
401
+ nextCur()
402
+ }
403
+ true
404
+ }
397
405
def next (): B = (if (hasNext) cur else empty).next()
398
406
}
399
407
@@ -405,6 +413,7 @@ trait Iterator[+A] extends TraversableOnce[A] {
405
413
* @note Reuse: $consumesAndProducesIterator
406
414
*/
407
415
def filter (p : A => Boolean ): Iterator [A ] = new AbstractIterator [A ] {
416
+ // TODO 2.12 - Make a full-fledged FilterImpl that will reverse sense of p
408
417
private var hd : A = _
409
418
private var hdDefined : Boolean = false
410
419
@@ -470,13 +479,27 @@ trait Iterator[+A] extends TraversableOnce[A] {
470
479
* @note Reuse: $consumesAndProducesIterator
471
480
*/
472
481
@ migration(" `collect` has changed. The previous behavior can be reproduced with `toSeq`." , " 2.8.0" )
473
- def collect [B ](pf : PartialFunction [A , B ]): Iterator [B ] = {
474
- val self = buffered
475
- new AbstractIterator [B ] {
476
- private def skip () = while (self.hasNext && ! pf.isDefinedAt(self.head)) self.next()
477
- def hasNext = { skip(); self.hasNext }
478
- def next () = { skip(); pf(self.next()) }
482
+ def collect [B ](pf : PartialFunction [A , B ]): Iterator [B ] = new AbstractIterator [B ] {
483
+ // Manually buffer to avoid extra layer of wrapping with buffered
484
+ private [this ] var hd : A = _
485
+
486
+ // Little state machine to keep track of where we are
487
+ // Seek = 0; Found = 1; Empty = -1
488
+ // Not in vals because scalac won't make them static (@inline def only works with -optimize)
489
+ // BE REALLY CAREFUL TO KEEP COMMENTS AND NUMBERS IN SYNC!
490
+ private [this ] var status = 0 /* Seek*/
491
+
492
+ def hasNext = {
493
+ while (status == 0 /* Seek*/ ) {
494
+ if (self.hasNext) {
495
+ hd = self.next()
496
+ if (pf.isDefinedAt(hd)) status = 1 /* Found*/
497
+ }
498
+ else status = - 1 /* Empty*/
499
+ }
500
+ status == 1 /* Found*/
479
501
}
502
+ def next () = if (hasNext) { status = 0 /* Seek*/ ; pf(hd) } else Iterator .empty.next()
480
503
}
481
504
482
505
/** Produces a collection containing cumulative results of applying the
@@ -578,33 +601,105 @@ trait Iterator[+A] extends TraversableOnce[A] {
578
601
* @note Reuse: $consumesOneAndProducesTwoIterators
579
602
*/
580
603
def span (p : A => Boolean ): (Iterator [A ], Iterator [A ]) = {
581
- val self = buffered
582
-
583
- // Must be a named class to avoid structural call to finish from trailing iterator
604
+ /*
605
+ * Giving a name to following iterator (as opposed to trailing) because
606
+ * anonymous class is represented as a structural type that trailing
607
+ * iterator is referring (the finish() method) and thus triggering
608
+ * handling of structural calls. It's not what's intended here.
609
+ */
584
610
class Leading extends AbstractIterator [A ] {
585
- private val drained = new mutable.Queue [A ]
586
- private var finished = false
587
- def finish (): Unit = {
588
- require(! finished)
589
- finished = true
590
- while (selfish) drained += self.next
611
+ var lookahead : mutable.Queue [A ] = null
612
+ var hd : A = _
613
+ /* Status is kept with magic numbers
614
+ * 1 means next element is in hd and we're still reading into this iterator
615
+ * 0 means we're still reading but haven't found a next element
616
+ * -1 means we are done reading into the iterator, so we must rely on lookahead
617
+ * -2 means we are done but have saved hd for the other iterator to use as its first element
618
+ */
619
+ var status = 0
620
+ private def store (a : A ) {
621
+ if (lookahead == null ) lookahead = new mutable.Queue [A ]
622
+ lookahead += a
623
+ }
624
+ def hasNext = {
625
+ if (status < 0 ) (lookahead ne null ) && lookahead.nonEmpty
626
+ else if (status > 0 ) true
627
+ else {
628
+ if (self.hasNext) {
629
+ hd = self.next()
630
+ status = if (p(hd)) 1 else - 2
631
+ }
632
+ else status = - 1
633
+ status > 0
634
+ }
591
635
}
592
- private def selfish = self.hasNext && p(self.head)
593
- def hasNext = if (finished) drained.nonEmpty else selfish
594
636
def next () = {
595
- if (finished) drained.dequeue()
596
- else if (selfish) self.next()
637
+ if (hasNext) {
638
+ if (status == 1 ) { status = 0 ; hd }
639
+ else lookahead.dequeue()
640
+ }
597
641
else empty.next()
598
642
}
643
+ def finish (): Boolean = {
644
+ if (status == - 1 ) false
645
+ else if (status == - 2 ) {
646
+ status = - 1
647
+ true
648
+ }
649
+ else {
650
+ if (status == 1 ) store(hd)
651
+ while (self.hasNext) {
652
+ val a = self.next()
653
+ if (p(a)) store(a)
654
+ else {
655
+ hd = a
656
+ status = - 1
657
+ return true
658
+ }
659
+ }
660
+ false
661
+ }
662
+ }
599
663
}
664
+
600
665
val leading = new Leading
666
+
601
667
val trailing = new AbstractIterator [A ] {
602
- private lazy val it = {
603
- leading.finish()
604
- self
668
+ private [this ] var myLeading = leading
669
+ /* Status flags meanings:
670
+ * -1 not yet accesssed
671
+ * 0 single element waiting in leading
672
+ * 1 defer to self
673
+ */
674
+ private [this ] var status = - 1
675
+ def hasNext = {
676
+ if (status > 0 ) self.hasNext
677
+ else {
678
+ if (status == 0 ) true
679
+ else if (myLeading.finish()) {
680
+ status = 0
681
+ true
682
+ }
683
+ else {
684
+ status = 1
685
+ myLeading = null
686
+ self.hasNext
687
+ }
688
+ }
605
689
}
606
- def hasNext = it.hasNext
607
- def next () = it.next()
690
+ def next () = {
691
+ if (hasNext) {
692
+ if (status > 0 ) self.next()
693
+ else {
694
+ status = 1
695
+ val ans = myLeading.hd
696
+ myLeading = null
697
+ ans
698
+ }
699
+ }
700
+ else Iterator .empty.next()
701
+ }
702
+
608
703
override def toString = " unknown-if-empty iterator"
609
704
}
610
705
@@ -618,18 +713,35 @@ trait Iterator[+A] extends TraversableOnce[A] {
618
713
* @return an iterator consisting of the remaining elements
619
714
* @note Reuse: $consumesAndProducesIterator
620
715
*/
621
- def dropWhile (p : A => Boolean ): Iterator [A ] = {
622
- val self = buffered
623
- new AbstractIterator [A ] {
624
- var dropped = false
625
- private def skip () =
626
- if (! dropped) {
627
- while (self.hasNext && p(self.head)) self.next()
628
- dropped = true
716
+ def dropWhile (p : A => Boolean ): Iterator [A ] = new AbstractIterator [A ] {
717
+ // Magic value: -1 = hasn't dropped, 0 = found first, 1 = defer to parent iterator
718
+ private [this ] var status = - 1
719
+ // Local buffering to avoid double-wrap with .buffered
720
+ private [this ] var fst : A = _
721
+ def hasNext : Boolean =
722
+ if (status == 1 ) self.hasNext
723
+ else if (status == 0 ) true
724
+ else {
725
+ while (self.hasNext) {
726
+ val a = self.next()
727
+ if (! p(a)) {
728
+ fst = a
729
+ status = 0
730
+ return true
731
+ }
629
732
}
630
- def hasNext = { skip(); self.hasNext }
631
- def next () = { skip(); self.next() }
632
- }
733
+ status = 1
734
+ false
735
+ }
736
+ def next () =
737
+ if (hasNext) {
738
+ if (status == 1 ) self.next()
739
+ else {
740
+ status = 1
741
+ fst
742
+ }
743
+ }
744
+ else Iterator .empty.next()
633
745
}
634
746
635
747
/** Creates an iterator formed from this iterator and another iterator
@@ -777,7 +889,7 @@ trait Iterator[+A] extends TraversableOnce[A] {
777
889
* is equal (as determined by `==`) to `elem`, `false` otherwise.
778
890
* @note Reuse: $consumesIterator
779
891
*/
780
- def contains (elem : Any ): Boolean = exists(_ == elem)
892
+ def contains (elem : Any ): Boolean = exists(_ == elem) // Note--this seems faster than manual inlining!
781
893
782
894
/** Finds the first value produced by the iterator satisfying a
783
895
* predicate, if any.
@@ -789,12 +901,11 @@ trait Iterator[+A] extends TraversableOnce[A] {
789
901
* @note Reuse: $consumesIterator
790
902
*/
791
903
def find (p : A => Boolean ): Option [A ] = {
792
- var res : Option [A ] = None
793
- while (res.isEmpty && hasNext) {
794
- val e = next()
795
- if (p(e)) res = Some (e)
904
+ while (hasNext) {
905
+ val a = next()
906
+ if (p(a)) return Some (a)
796
907
}
797
- res
908
+ None
798
909
}
799
910
800
911
/** Returns the index of the first produced value satisfying a predicate, or -1.
@@ -807,15 +918,11 @@ trait Iterator[+A] extends TraversableOnce[A] {
807
918
*/
808
919
def indexWhere (p : A => Boolean ): Int = {
809
920
var i = 0
810
- var found = false
811
- while (! found && hasNext) {
812
- if (p(next())) {
813
- found = true
814
- } else {
815
- i += 1
816
- }
921
+ while (hasNext) {
922
+ if (p(next())) return i
923
+ i += 1
817
924
}
818
- if (found) i else - 1
925
+ - 1
819
926
}
820
927
821
928
/** Returns the index of the first occurrence of the specified
@@ -829,15 +936,11 @@ trait Iterator[+A] extends TraversableOnce[A] {
829
936
*/
830
937
def indexOf [B >: A ](elem : B ): Int = {
831
938
var i = 0
832
- var found = false
833
- while (! found && hasNext) {
834
- if (next() == elem) {
835
- found = true
836
- } else {
837
- i += 1
838
- }
939
+ while (hasNext) {
940
+ if (next() == elem) return i
941
+ i += 1
839
942
}
840
- if (found) i else - 1
943
+ - 1
841
944
}
842
945
843
946
/** Creates a buffered iterator from this iterator.
0 commit comments