Java中读取输入方式的性能比较

程序开发过程中,需要从键盘获取输入值是常有的事,但Java它偏偏就没有像c语言给我们提供的scanf(),C++给我们提供的cin()获取键盘输入值的现成函数!Java没有提供这样的函数也不代表遇到这种情况我们就束手无策,请你看以下三种解决方法吧:

  1. 使用System.out.read()从控制台接收一个字符,只能针对一个字符的获取,同时,获取进来的变量的类型只能是char,当我们输入一个数字,希望得到的也是一个整型变量的时候,我们还得修改其中的变量类型,这样就显得比较麻烦。
  2. 用BufferedReader类和InputStreamReader类从控制台接收一个字符串,然后再对字符串进行处理。
  3. 最简单,最强大的,就是用Scanner类。

 最常用的莫过于Scanner 类了,简单强大,但如果输入数据巨大的话,就另当别论了。下面看一个POJ上的查并集的例子。

用Scanner 读取数据

package Search_Union_Set;

import java.util.Scanner;
/*Memory:5844K	Time:4235MS*/
public class Poj_2524_WithScanner {

	static int MAXN = 50001;
	static int pa[] = new int[MAXN];
	static int rank[] = new int[MAXN];
	static int count;

	static void make_set(int x) {
		pa[x] = x;
		rank[x] = 0;
	}

	static int find_set(int x) {
		int r = x, temp;
		while (pa[r] != r)
			r = pa[r];
		while (x != r) {
			temp = pa[x];
			pa[x] = r;
			x = temp;
		}
		return x;
	}

	static void union_set(int x, int y) {
		x = find_set(x);
		y = find_set(y);
		if (x == y)
			return;
		if (rank[x] > rank[y]) {
			pa[y] = x;
		} else {
			pa[x] = y;
			if (rank[x] == rank[y])
				rank[y]++;
		}
		count--;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		int n, m, x, y, i;
		int time = 0;
		while (true) {
			n = sc.nextInt();
			m = sc.nextInt();
			count = n;
			if (m == n && n == 0)
				break;
			if (m == 0) {
				System.out.println("1");
				continue;
			}
			for (i = 0; i < n; i++)
				make_set(i);
			for (i = 0; i < m; i++) {
				x = sc.nextInt();
				y = sc.nextInt();
				union_set(x, y);
				x = y;
			}
			time++;
			System.out.println("Case " + time + ": " + count);
		}
	}
}

用BufferedReader类和InputStreamReader类从控制台接收

package Search_Union_Set;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
/*Memory:5260K	Time:719MS*/
public class Poj_2524_WithBufferedReader {
	
	static int MAXN = 50001; 
	static int pa[] = new int[MAXN]; 
	static int rank[] = new int[MAXN]; 
	static int count;
	static void make_set(int x) {
		pa[x] = x;
		rank[x] = 0;
	}

	static int find_set(int x) {
		int r = x, temp;
		while (pa[r] != r)
			r = pa[r];
		while (x != r) {
			temp = pa[x];
			pa[x] = r;
			x = temp;
		}
		return x;
	}

	static void union_set(int x, int y) {
		x = find_set(x);
		y = find_set(y);
		if (x == y)
			return;
		if (rank[x] > rank[y])
		{
			pa[y] = x;
		} else {
			pa[x] = y;
			if (rank[x] == rank[y])
				rank[y]++;
		}
		count--;
	}

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int n, m, x, y, i;
		int time = 0;
		while (true) {
			String str = br.readLine();
			StringTokenizer stoken = new StringTokenizer(str, " ");
			n = Integer.valueOf(stoken.nextToken());
			m = Integer.valueOf(stoken.nextToken());
			count = n;
			if (m == n && n == 0)
				break;
			if (m == 0) {
				System.out.println("1");
				continue;
			}
			for (i = 0; i < n; i++)
				make_set(i);
			for (i = 0; i < m; i++) {
				str = br.readLine();
				stoken = new StringTokenizer(str, " ");
				x = Integer.valueOf(stoken.nextToken());
				y = Integer.valueOf(stoken.nextToken());
				union_set(x, y);
				x = y;
			}
			time++;
			System.out.println("Case " + time + ": " + count);
		}
	}
}

用BufferedReader类和InputStreamReader类明显要比Scanner 快得多。

Scanner一个可以使用正则表达式来分析基本类型和字符串的简单文本扫描器。 Scanner 使用分隔符模式将其输入分解为标记,默认情况下该分隔符模式与空白匹配。然后可以使用不同的 next 方法将得到的标记转换为不同类型的值。

BufferedReader从字符输入流中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取。 可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。 通常,Reader 所作的每个读取请求都会导致对基础字符或字节流进行相应的读取请求。因此,建议用 BufferedReader 包装所有其 read() 操作可能开销很高的 Reader(如 FileReader 和 InputStreamReader)。

InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,否则可能接受平台默认的字符集。 每次调用 InputStreamReader 中的一个 read() 方法都会导致从基础输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从基础流读取更多的字节,使其超过满足当前读取操作所需的字节。

版权声明:本文为博主原创文章,未经博主允许不得转载。

posted @ 2014-01-21 22:46  InkGenius  阅读(448)  评论(0编辑  收藏  举报