Faster Scanner in Scala

Правка en1, от wrick, 2015-10-19 22:32:29

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://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()

  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

Теги scala, java, fast input, input reading, scanner

История

 
 
 
 
Правки
 
 
  Rev. Язык Кто Когда Δ Комментарий
en5 Английский wrick 2015-10-26 08:10:34 800
en4 Английский wrick 2015-10-21 10:28:35 356
en3 Английский wrick 2015-10-21 10:24:45 0 (published)
en2 Английский wrick 2015-10-20 00:05:47 197 (saved to drafts)
en1 Английский wrick 2015-10-19 22:32:29 2493 Initial revision (published)