我正在尝试将java.util.StringTokenizer
转换为Scala的Iterator
,但以下方法失败:
def toIterator(st: StringTokenizer): Iterator[String] =
Iterator.continually(st.nextToken()).takeWhile(_ => st.hasMoreTokens()))
但是这个有效:
def toIterator(st: StringTokenizer): Iterator[String] =
Iterator.fill(st.countTokens())(st.nextToken())
你可以在Scala控制台中看到这个:
scala> Iterator("a b", "c d").map(new java.util.StringTokenizer(_)).flatMap(st => Iterator.continually(st.nextToken()).takeWhile(_ => st.hasMoreTokens())).toList
res1: List[String] = List(a, c)
scala> Iterator("a b", "c d").map(new java.util.StringTokenizer(_)).flatMap(st => Iterator.fill(st.countTokens())(st.nextToken())).toList
res2: List[String] = List(a, b, c, d)
如你所见,res1
是错误的,而 res2
是正确的。我做错了什么?第一种方法应该可行并且更好,因为它比第二种方法快2倍,因为它不会扫描字符串两次。
takeWhile(f)
方法的问题所在。它本质上像是一个do yield next() while f
而不是while(f) yield x
。 - pathikritdo tmp = next(); break unless f(tmp); yield tmp while true
。break
在从内部迭代器获取下一个元素之后但在从外部迭代器中产生它之前发生。 - Silvio Mayolospan
或takeUntil
工具会很不错,它可以在这种情况下工作(再次强调,封装更好,但只是作为一种练习)。 - pathikrit