背景:
在一些算法题中,由于数据量过大,可能会出现卡输入输出时间
的问题
原理:
在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);
4.
StringTokenizer类默认的分隔符是" "
可以设置为其他的分隔符,如","