背景:
在一些算法题中,由于数据量过大,可能会出现卡输入输出时间
的问题
原理:
在Java中,输入通常是使用Scanner,输出使用System.out,先说输入
Scanner in = new Scanner(System.in);
慢的原因有两方面:
- System.in在读取的时候是
字节流
进行读取,是一个字节一个字节读取的,在读取大文件时,这样的读取方式较慢 - 要读取的数据一般都是被存储到
文件之中
,所以in的读取操作实际上是在进行IO交互
,而IO交互的速度很慢
改进方法:
- 改为使用
字符流
Reader - 字符流仍然无法解决频繁的IO交互,可以使用Reader的子类
BufferReader
,这是带有缓冲区的Reader,在读取时,会现将文件中的所有数据放到缓冲区(内存)之中,之后的每次读取都是直接读内存,减少了IO交互的频率,大大提高效率
代码模板:
package Test;import java.util.*;
import java.io.*;public class Main
{public static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));public static Read in = new Read();public static void main(String[] args) throws IOException{// 写代码out.close();}
}class Read // 自定义快速读入
{StringTokenizer st = new StringTokenizer("");BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));// 将字节流转化为字符流String next() throws IOException{while(!st.hasMoreTokens()){st = new StringTokenizer(bf.readLine());}return st.nextToken();}String nextLine() throws IOException{return bf.readLine();}int nextInt() throws IOException{return Integer.parseInt(next());}long nextLong() throws IOException{return Long.parseLong(next());}double nextDouble() throws IOException{return Double.parseDouble(next());}
}
说明:
1.
Read
类是定义的快读类,核心代码是:
StringTokenizer st = new StringTokenizer("");BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
第二行代码就是完成上述的改进工作,将字节流转化为字符流,同时使用带有缓冲区的字符流BufferedReader
在读取的时候是一行一行
进行读取的,一行中可能包含多个数据,通过StringTokenizer st
实现字符串裁剪,根据空格裁剪依次得到一行中所有数据
2.
快写的实现思路和快读相同
public static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));// 快写
3.
快读和快写类的用法和之前的输入输出类的用法一致
in.next();out.println(1);