We all know that `java.util.Scanner` [is slow](https://www.cpe.ku.ac.th/~jim/java-io.html). ↵
↵
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://codeforces.me/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↵
↵
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://codeforces.me/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↵