java快速IO【ACM模板】

前言

       可以不看,就唠唠嗑(滑稽)。
       相信学习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需求。但这仅仅只是模板,伙伴们可以根据自己实际的需求进行改进。

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

### Java ACM竞赛代码模板 对于参与ACM竞赛的选手而言,拥有一个高效且结构清晰的代码模板至关重要。下面提供了一个适用于Java编程语言的基础模板,该模板包含了输入取、基本数据处理以及输出打印等功能。 ```java import java.io.*; import java.util.*; public class Main { static class InputReader { private final InputStream stream; private final byte[] buf = new byte[8192]; private int curChar, snumChars; public InputReader(InputStream stream) { this.stream = stream; } public int read() { if (snumChars == -1) throw new InputMismatchException(); if (curChar >= snumChars) { curChar = 0; try { snumChars = stream.read(buf); } catch (IOException e) { throw new InputMismatchException(); } if (snumChars <= 0) return -1; } return buf[curChar++]; } public String nextLine() { StringBuilder ret = new StringBuilder(64); int c = skip(); while (c != '\n' && c != '\r') { ret.append((char)c); c = read(); } return ret.toString(); } public int nextInt() { int c = skip(); int sgn = 1; if (c == '-') { sgn = -1; c = read(); } int res = 0; do { if (c < '0' || c > '9') throw new InputMismatchException(); res *= 10; res += c - '0'; c = read(); } while (!isSpaceChar(c)); return res * sgn; } private boolean isSpaceChar(int c) { return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1; } private char skip() { int c; while ((c = read()) <= 32 && c != -1); return (char)c; } } public static void main(String args[]) throws Exception { InputReader in = new InputReader(System.in); PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))); // Your solution starts here int n = in.nextInt(); // Example input reading // Process the problem logic and generate output out.println(n); // Example output writing out.close(); } } ``` 此模板定义了一个`InputReader`类用于快速入数据,并通过标准输入流获取整数或字符串类型的数值;同时利用`PrintWriter`对象来实现高效的输出操作[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值