We all know that java.util.Scanner is slow.
Here is a version in Scala that is idiomatic (you can do all the Collections API e.g. .take, .map, .filter etc) and supports line numbers too and is much faster than the Java Scanner:
import java.io._
import java.nio.file.{Files, Path}
import java.util.StringTokenizer
import scala.io.Codec
/**
* Scala implementation of a faster java.util.Scanner
* See: http://mirror.codeforces.com/blog/entry/7018
*/
class Scanner(reader: LineNumberReader) extends Iterable[String] with AutoCloseable {
def this(reader: BufferedReader) = this(new LineNumberReader(reader))
def this(reader: Reader) = this(new BufferedReader(reader))
def this(inputStream: InputStream)(implicit codec: Codec) = this(new InputStreamReader(inputStream, codec.charSet))
def this(path: Path)(implicit codec: Codec) = this(Files.newBufferedReader(path, codec.charSet))
def this(file: File)(implicit codec: Codec) = this(file.toPath)(codec)
def this(str: String) = this(new StringReader(str))
override def iterator = for {
line <- Iterator.continually(reader.readLine()).takeWhile(_ != null)
tokenizer = new StringTokenizer(line)
tokens <- Iterator.continually(tokenizer).takeWhile(_.hasMoreTokens)
} yield tokens.nextToken()
private[this] var current = iterator
def hasNext = current.hasNext
@inline def next() = current.next()
/**
* This is different from Java's scanner.nextLine
* The Java one is a misnomer since it actually travel to end of current line
* This one actually does fetch the next line
*/
def nextLine(): String = {
val line = reader.readLine()
current = iterator
line
}
def lineNumber: Int = reader.getLineNumber
def nextString(): String = next()
def nextBoolean(): Boolean = next().toBoolean
def nextByte(radix: Int = 10): Byte = java.lang.Byte.parseByte(next(), radix)
def nextShort(radix: Int = 10): Short = java.lang.Short.parseShort(next(), radix)
def nextInt(radix: Int = 10): Int = java.lang.Integer.parseInt(next(), radix)
def nextLong(radix: Int = 10): Long = java.lang.Long.parseLong(next(), radix)
def nextBigInt(radix: Int = 10): BigInt = BigInt(next(), radix)
def nextFloat(): Float = next().toFloat
def nextDouble(): Double = next().toDouble
def nextBigDecimal(): BigDecimal = BigDecimal(next())
override def close() = reader.close()
}
Source: https://github.com/pathikrit/ScalaForces/blob/master/src/main/scala/Scanner.scala
Benchmarks: https://github.com/pathikrit/better-files/tree/master/benchmarks




