目录

  • 前言
  • 正题
  • 模板1
  • 模板2
  • 模板3


前言

       可以不看,就唠唠嗑(滑稽)。
       相信学习java的xdm(or jmm)都难逃学习算法的这一过程,但是接触算法的时候会发现,几乎所有的算法书都是以c/c++作为实现语言的。这是为什么呢?最主要的原因就是因为c/c++的执行速度是非常高的。
       java相对于c/c++的执行速度是比较慢的,这是为什么呢?
       因为java程序的执行依靠的是JVM(java虚拟机),而JVM是一个比较完善的虚拟机,由c++编写,它会自动进行内存管理防止内存泄漏等操作,这些操作也会花费时间。执行c/c++程序就不一样了,内存管理需要人为的写出代码,那如果我不去管它,就可以节省出这些时间。因为评价算法的指标是时间和空间复杂度,与内存的管理无关,所以我们完全可以省略掉这一步骤。
       当然,原因不止这一个,这里就不一一阐述了,下面我们开始进入正题。

正题

对于java的输入输出,我相信大部分的小伙伴第一时间就是想到:

//输入
 Scanner in=new Scanner(System.in);
 int n=in.nextInt();
 //输出
 System.out.println(n);

这非常简单,为什么这么简单,那当然是因为底层做了很多你不知道的事。所以简单带来的负面影响就是效率低下。所有的测评环境对于这种效率低下的东西容忍度都是zero,因为它会卡时间。所以很多用java写代码的伙伴们就经常会看到”超出时间限制“这几个字,起初我也特别苦恼,但是后来通过学习,get到了一些高效的方式。见下文:

模板1

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.StringTokenizer;

public class Main{
	public static void main(String[] args){
		 QuickInput in = new  QuickInput();
		PrintWriter out = new PrintWriter(System.out);
		
		//in.nextInt().....
		//out.println().....
		
		out.close();//不关闭,就会有些数据留在缓冲区
	}
}


class  QuickInput
{
    BufferedReader buf;
    StringTokenizer tok;
     QuickInput(){
        buf = new BufferedReader(new InputStreamReader(System.in));
    }
    boolean hasNext(){
        while(tok == null || !tok.hasMoreElements()){
            try{
                tok = new StringTokenizer(buf.readLine());
            }catch(Exception e){
                return false;
            }
        }
        return true;
    }
    String next(){
        if(hasNext()) return tok.nextToken();
        return null;
    }
    int nextInt(){
        return Integer.parseInt(next());
    }
    long nextLong(){
        return Long.parseLong(next());
    }
    double nextDouble(){
        return Double.parseDouble(next());
    }
    BigInteger nextBigInteger(){
        return new BigInteger(next());
    }
    BigDecimal nextBigDecimal(){
        return new BigDecimal(next());
    }
}

这里自定义了一个类,模仿Scanner类。这样更加方便记忆。
使用的时候new一个对象调用对应方法便可。
注意:
    1.空白字符是无法读入的,因为空白字符是作为默认的分隔符
    2.可以自定义分隔符,创建StringTokenizer对象时使用构造方法:StringTokenizer(String str, String delim),参数delim为分隔符组成的字符串。例如new StringTokenizer(buf.readLine(),“ab”),那么分隔符为字符a和b
    3.StringTokenizer类对参数字符串做划分与String类的split方法并不一样,StringTokenizer做划分的时候连续的分隔符并不会产生空字符串。
    4.对于多组输入,可以在BufferedReader对象读取数据的时候进行判空来结束输入。

模板2

import java.io.*;

public class Main{
	public static void main(String[] args) throws IOException{
		BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter out=new BufferedWriter(new OutputStreamWriter(System.out));
		
		//in.read(),in.readLine().....
		//out.write()......
		
		in.close();
		out.close();//关流,不然有些数据还在缓冲区
	}
}

模板2其实就是模板1的简化版,对于输入数据的单位是以行为单位的时候就可以使用模板2。并采用BufferedWriter类来进行输出,没有print系列方法,使用write系列方法进行输出
对于多组输入,同上:在BufferedReader对象读取数据的时候进行判空来结束输入。

模板3

import java.io.*;
 
public class Main{
	public static void main(String[] args) throws IOException {
		
		StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
		PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
		
		//in.nextToken()    :解析下一个标记
		//in.nval           :标记的double值
		//例如:int a=(int)in.nval;
		//或者:double b=in.nval;
		//in.sval           :标记的String值
		//例如:String str=sval;
		
		//如果当前的数据是数字,就通过in.nval字段获取对应值
		//如果是字符串,就通过in.sval字段获取对应值
		 
		//例如:读取10个double型数字并打印
		for(int i=0;i<10;++i){
			//这里的nextToken方法是会抛出异常的,为了代码的简洁,就直接在main方法使用throws声明异常的抛出
			in.nextToken();
			out.println(in.nval);
		}
		out.close();
	}
}

注意:
    1.空白字符都是分隔符,默认只解析“字母,数字,空白字符,字符串引号中的内容和注释内容”,字母,数字以及引号中的内容被认为是标记的构成,空白字符为分隔符,注释内容不解析
    2.以数字开头的标记是不能被解析为字符串的,例如:”45abc“,将会被解析成两个标记,分别为数字(45.0)、字符串(abc)。
    3.其他不能解析的每个字符都会被解析为一个null
    4.in.wordChars(int low,int hight)        //新增标记的构成字符范围
    5.in.quoteChar(int ch)                        //新增分割符
    6.对于多组数据,可以判断in.nextToken()的返回值是否等于StreamTokenizer.TT_EOF便可,若等于说明到达流的末尾。




以上就是三个版本的快速IO方式,可以解决很大一部分的IO需求。但这仅仅只是模板,伙伴们可以根据自己实际的需求进行改进。

虽然以上模板不符合项目开发的要求,忽略了数据的安全性等等,但是对于算法测评来说,完全可以忽略这些。