Java의 System.in에서 읽는 가장 빠른 방법은 무엇입니까?
나는 표준에서 공백이나 줄 바꿈으로 구분 된 정수 무리를 읽고 Scanner(System.in)
있습니다.
Java에서이 작업을 수행하는 더 빠른 방법이 있습니까?
Java에서이 작업을 수행하는 더 빠른 방법이 있습니까?
예. 스캐너가 상당히 느립니다 (적어도 내 경험에 따르면).
입력을 확인할 필요가 없다면 BufferedInputStream에 스트림을 래핑하고 String.split
/ 와 같은 것을 사용하는 것이 좋습니다 Integer.parseInt
.
작은 비교 :
읽기 17메가바이트 이 코드를 사용하여 (4233600 개 번호)
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext())
sum += scanner.nextInt();
내 컴퓨터에 3.3 초가 걸렸습니다 . 이 스 니펫 동안
BufferedReader bi = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = bi.readLine()) != null)
for (String numStr: line.split("\\s"))
sum += Integer.parseInt(numStr);
0.7 초가 걸렸 습니다 .
더 코드를 엉망으로 (이상 반복 line
하여 String.indexOf
/ String.substring
당신은 아주 쉽게 약 0.1 초에 내려받을 수),하지만 난 당신의 질문에 대답 한 나는 몇 가지 코드 골프 이것을 설정하지 않으려는 생각합니다.
Java의 스캐너처럼 작동하지만 속도면에서 여러 크기로 성능을 능가 하는 작은 InputReader 클래스를 만들었습니다. 사실 BufferedReader도 능가합니다. 다음은 표준 입력에서 다른 유형의 데이터를 읽는 데 만든 InputReader 클래스의 성능을 보여주는 막대 그래프입니다.
다음은 InputReader 클래스를 사용하여 System.in에서 오는 모든 숫자의 합계를 찾는 두 가지 방법입니다.
int sum = 0;
InputReader in = new InputReader(System.in);
// Approach #1
try {
// Read all strings and then parse them to integers (this is much slower than the next method).
String strNum = null;
while( (strNum = in.nextString()) != null )
sum += Integer.parseInt(strNum);
} catch (IOException e) { }
// Approach #2
try {
// Read all the integers in the stream and stop once an IOException is thrown
while( true ) sum += in.nextInt();
} catch (IOException e) { }
경쟁 프로그래밍 관점에서 질문하는 경우 제출이 충분히 빠르지 않으면 TLE가됩니다.
그런 다음 System.in에서 String을 검색하기 위해 다음 메서드를 확인할 수 있습니다. 나는 자바 (경쟁 사이트)에서 최고의 코더 중 하나에서 가져 왔습니다.
private String ns()
{
int b = skip();
StringBuilder sb = new StringBuilder();
while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
sb.appendCodePoint(b);
b = readByte();
}
return sb.toString();
}`
당신은 System.in
숫자 방식으로 숫자에서 읽을 수 있습니다 . 이 답변을보십시오 : https://stackoverflow.com/a/2698772/3307066 .
여기에 코드를 복사합니다 (거의 수정). 기본적으로 숫자가 아닌 것으로 구분 된 정수를 읽습니다. (원저자에 대한 크레딧.)
private static int readInt() throws IOException {
int ret = 0;
boolean dig = false;
for (int c = 0; (c = System.in.read()) != -1; ) {
if (c >= '0' && c <= '9') {
dig = true;
ret = ret * 10 + c - '0';
} else if (dig) break;
}
return ret;
}
내 문제 에서이 코드는 약이었습니다. 을 (를) 사용 StringTokenizer
하는 것보다 2 배 빠르며 이미 String.split(" ")
. (문제는 각각 최대 1 백만 개의 정수 1 백만 개를 읽는 것과 관련이 있습니다.)
StringTokenizer
토큰으로 구분 된 문자열 입력을 읽는 훨씬 빠른 방법입니다.
공백으로 구분 된 정수 문자열을 읽고 arraylist에 저장하려면 아래 예제를 확인하십시오.
String str = input.readLine(); //read string of integers using BufferedReader e.g. "1 2 3 4"
List<Integer> list = new ArrayList<>();
StringTokenizer st = new StringTokenizer(str, " ");
while (st.hasMoreTokens()) {
list.add(Integer.parseInt(st.nextToken()));
}
프로그래밍 관점에서이 사용자 정의 된 스캔 및 인쇄 클래스는 Java 내장 Scanner 및 BufferedReader 클래스보다 훨씬 좋습니다.
import java.io.InputStream;
import java.util.InputMismatchException;
import java.io.IOException;
public class Scan
{
private byte[] buf = new byte[1024];
private int total;
private int index;
private InputStream in;
public Scan()
{
in = System.in;
}
public int scan() throws IOException
{
if(total < 0)
throw new InputMismatchException();
if(index >= total)
{
index = 0;
total = in.read(buf);
if(total <= 0)
return -1;
}
return buf[index++];
}
public int scanInt() throws IOException
{
int integer = 0;
int n = scan();
while(isWhiteSpace(n)) /* remove starting white spaces */
n = scan();
int neg = 1;
if(n == '-')
{
neg = -1;
n = scan();
}
while(!isWhiteSpace(n))
{
if(n >= '0' && n <= '9')
{
integer *= 10;
integer += n-'0';
n = scan();
}
else
throw new InputMismatchException();
}
return neg*integer;
}
public String scanString()throws IOException
{
StringBuilder sb = new StringBuilder();
int n = scan();
while(isWhiteSpace(n))
n = scan();
while(!isWhiteSpace(n))
{
sb.append((char)n);
n = scan();
}
return sb.toString();
}
public double scanDouble()throws IOException
{
double doub=0;
int n=scan();
while(isWhiteSpace(n))
n=scan();
int neg=1;
if(n=='-')
{
neg=-1;
n=scan();
}
while(!isWhiteSpace(n)&& n != '.')
{
if(n>='0'&&n<='9')
{
doub*=10;
doub+=n-'0';
n=scan();
}
else throw new InputMismatchException();
}
if(n=='.')
{
n=scan();
double temp=1;
while(!isWhiteSpace(n))
{
if(n>='0'&&n<='9')
{
temp/=10;
doub+=(n-'0')*temp;
n=scan();
}
else throw new InputMismatchException();
}
}
return doub*neg;
}
public boolean isWhiteSpace(int n)
{
if(n == ' ' || n == '\n' || n == '\r' || n == '\t' || n == -1)
return true;
return false;
}
public void close()throws IOException
{
in.close();
}
}
그리고 사용자 정의 된 Print 클래스는 다음과 같습니다.
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class Print
{
private BufferedWriter bw;
public Print()
{
this.bw = new BufferedWriter(new OutputStreamWriter(System.out));
}
public void print(Object object)throws IOException
{
bw.append("" + object);
}
public void println(Object object)throws IOException
{
print(object);
bw.append("\n");
}
public void close()throws IOException
{
bw.close();
}
}
BufferedReader를 사용하여 데이터를 읽을 수 있습니다.
BufferedReader inp = new BufferedReader(new InputStreamReader(System.in));
int t = Integer.parseInt(inp.readLine());
while(t-->0){
int n = Integer.parseInt(inp.readLine());
int[] arr = new int[n];
String line = inp.readLine();
String[] str = line.trim().split("\\s+");
for(int i=0;i<n;i++){
arr[i] = Integer.parseInt(str[i]);
}
그리고 인쇄를 위해 StringBuffer를 사용하십시오.
StringBuffer sb = new StringBuffer();
for(int i=0;i<n;i++){
sb.append(arr[i]+" ");
}
System.out.println(sb);
참고 URL : https://stackoverflow.com/questions/7049011/whats-the-fastest-way-to-read-from-system-in-in-java
'Development Tip' 카테고리의 다른 글
PostgreSQL 정규식 단어 경계? (0) | 2020.12.08 |
---|---|
jQuery val () 및 확인란 (0) | 2020.12.08 |
C # 컴파일러가 IEnumerable 간의 명시 적 캐스트를 허용하는 이유 (0) | 2020.12.08 |
Node.js에서 버퍼를 ReadableStream으로 변환 (0) | 2020.12.08 |
사용자 수준 스레드와 커널 지원 스레드의 차이점은 무엇입니까? (0) | 2020.12.08 |