@@ -91,6 +91,11 @@ trait IndexedSeqOps[+A, +CC[_], +C] extends Any with SeqOps[A, CC, C] { self =>
91
91
92
92
override def slice (from : Int , until : Int ): C = fromSpecific(new IndexedSeqView .Slice (this , from, until))
93
93
94
+ override def sliding (size : Int , step : Int ): Iterator [C ] = {
95
+ require(size >= 1 && step >= 1 , f " size= $size%d and step= $step%d, but both must be positive " )
96
+ new IndexedSeqSlidingIterator [A , CC , C ](this , size, step)
97
+ }
98
+
94
99
override def head : A =
95
100
if (! isEmpty) apply(0 )
96
101
else throw new NoSuchElementException (s " head of empty ${
@@ -145,3 +150,26 @@ trait IndexedSeqOps[+A, +CC[_], +C] extends Any with SeqOps[A, CC, C] { self =>
145
150
}
146
151
}
147
152
}
153
+
154
+ /** A fast sliding iterator for IndexedSeqs which uses the underlying `slice` operation. */
155
+ private final class IndexedSeqSlidingIterator [A , CC [_], C ](s : IndexedSeqOps [A , CC , C ], size : Int , step : Int )
156
+ extends AbstractIterator [C ] {
157
+
158
+ private [this ] val len = s.length
159
+ private [this ] var pos = 0
160
+ private def chklen : Boolean = len == s.length || {
161
+ throw new java.util.ConcurrentModificationException (" collection size changed during iteration" )
162
+ false
163
+ }
164
+
165
+ def hasNext : Boolean = chklen && pos < len
166
+
167
+ def next (): C = if (! chklen || ! hasNext) Iterator .empty.next() else {
168
+ val end = { val x = pos + size; if (x < 0 || x > len) len else x } // (pos.toLong + size).min(len).toInt
169
+ val slice = s.slice(pos, end)
170
+ pos =
171
+ if (end >= len) len
172
+ else { val x = pos + step; if (x < 0 || x > len) len else x } // (pos.toLong + step).min(len).toInt
173
+ slice
174
+ }
175
+ }
0 commit comments