1.Scanner与System.out为什么慢
Scanner读取速度慢的原因:
在ACM模式下,输入数据和输出数据时,他会将数据放在一个文件里面
在new上一个Scanner时,去调用一个next()方法,他会去访问IO设备,每次从文件夹中拿出一个数据,每调用一次next就要访问一次IO设备,而每次调用IO设备的速度是很慢的,当需要输入的数据很多时就会造成程序的超时
System.out输出慢的原因:
System.out输出慢的原因与Scanner读取慢的原因类似,每次使用System.out输出数据时,他会每输出一个数据,就会访问IO设备,将这个数据放到文件夹里面,每次只放一个数据,也是由于访问IO设备的速度较慢,当数据过多时,就会造成程序运行超时的情况
2.解决办法——自定义快读模版
java在处理IO时,有两套标准:
1.字节流:(System.in)
2.字符流:(new InputStreamReader()),以Reader或者是Writer结尾的几乎就是字符流
第一步:
System.in从输入设备读取数据,因为是字节流,所以通过InputStreamReader转化为字符流
new InputStreamReader(System.in)
第二步:
BufferedReader是一个带内存缓冲区的字符流
BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
BufferedReader是将数据全部放进内存缓冲区里面,只需要访问一次,在调用next方法从内存缓冲区里面一个一个拿数据,在内存里面拿数据就快很多了
第三步:
字符串裁剪
StringTokenizer表示字符串裁剪
StringTokenizer st=new StringTokenizer("");
StringTokenizer的使用:
1. 创建对象:
通过构造函数创建StringTokenizer对象,传入要分割的字符串和分隔符。
例如,StringTokenizer st = new StringTokenizer("hello,world,java", ",");这里以逗号作为分隔符分割字符串“hello,world,java”。
2. 获取子字符串:
可以使用hasMoreTokens()方法判断是否还有未获取的子字符串,使用nextToken()方法获取下一个子字符串。
例如,在上面的例子中,可以通过循环调用hasMoreTokens()和nextToken()来获取每个被逗号分隔的子字符串。
String next()throws IOException {
while(!st.hasMoreTokens()){
st=new StringTokenizer(bf.readLine());
}
return st.nextToken();
}
上面这个代码的逻辑是先判断st里面有没分割的字符串,如果有就不读取,返回st里面相对的第一个分割好的字符串,如果没有就读取一行数据,对其进行分割放进st里面,从而就可以按顺序获取对应的数据了
第四步:
编写获取对应数据的方法
nextLine方法:直接返回一行数据,调用bf读取一行数据返回就行
nextInteger,nextDouble,nextLong等方法,调用next获取到对应裁剪的字符串,然后调用对应数据类型的parse方法将其类型转换成对应的数据类型返回
String nextLine()throws IOException{
return bf.readLine();
}
int nextInteger()throws IOException{
return Integer.parseInt(next());
}
double nextDouble()throws IOException{
return Double.parseDouble(next());
}
long nextLong()throws IOException{
return Long.parseLong(next());
}
以上对应的是Scanner方法,将所有的方法放进Read类里面,创建一个Read对象,通过对象调用里面的方法,调用Read的方法和调用Scanner方法的形式是一样的
第五步:
将字节流转化为字符流
new OutputStreamWriter(System.out)
第六步:
将数据放进内存缓冲区里面
new BufferedWriter(new OutputStreamWriter(System.out))
第七步:
在套一个PrintWriter
虽然BufferedWriter里面也有输出方式,但是不太好写,使用PrintWriter,可以和System.out输出一样
public static PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
3.自定义快读模版代码
import java.io.*;
import java.util.StringTokenizer;
public class test3 {
public static PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
public static Read in=new Read();
public static void main(String[] args) {
Read in=new Read();
}
static class Read{//自定义快速读入
//字符串截取
StringTokenizer st=new StringTokenizer("");
//System.in是字节流
//InputStreamReader是字符流
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());
}
double nextDouble()throws IOException{
return Double.parseDouble(next());
}
long nextLong()throws IOException{
return Long.parseLong(next());
}
}
}