Jaki jest najszybszy sposób czytania z System.in w Javie?
Czytam kilka liczb całkowitych oddzielonych spacjami lub znakami nowej linii od standardu w użyciu Scanner(System.in)
.
Czy Jest jakiś szybszy sposób na zrobienie tego w Javie?
9 answers
Tak. Skaner jest dość powolny (przynajmniej według mojego doświadczenia).Czy Jest jakiś szybszy sposób na zrobienie tego w Javie?
Jeśli nie musisz sprawdzać poprawności danych wejściowych, proponuję po prostu zawinąć strumień w BufferedInputStream i użyć czegoś takiego String.split
/ Integer.parseInt
.
Małe porównanie:
Odczyt 17 megabajtów (4233600 numerów) przy użyciu tego kodu
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext())
sum += scanner.nextInt();
Took on my machine 3.3 sekund . while this snippet
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);
Zajęło 0,7 sekundy .
Przez dalsze zamieszanie w kodzie (iteracja nad line
z String.indexOf
/ String.substring
) można go dostać się do około 0.1 sekundy dość łatwo, ale myślę, że odpowiedziałem na twoje pytanie i nie chcę, aby przekształcić to w jakiś kod golf.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-13 07:05:32
Stworzyłem małą klasęInputReader , która działa tak samo jak Scanner Javy, ale przewyższa ją szybkością o wiele wielkości, w rzeczywistości przewyższa również BufferedReader. Oto wykres słupkowy, który pokazuje wydajność stworzonej przeze mnie klasy InputReader odczytującej różne typy danych ze standardowego wejścia:
Oto dwa różne sposoby znajdowania sumy wszystkich liczb pochodzących z System.in użycie klasy InputReader:
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) { }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-06 18:07:00
Jeśli pytasz z konkurencyjnego punktu widzenia programowania, gdzie jeśli zgłoszenie nie jest wystarczająco szybkie, to będzie TLE.
Następnie możesz sprawdzić następującą metodę, aby pobrać ciąg z System.in.
Wziąłem z jednego z najlepszych programistów w Javie (konkurencyjne strony)
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();
}`
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-07 07:36:30
Możesz czytać z System.in
cyfra po cyfrze. Spójrz na tę odpowiedź: https://stackoverflow.com/a/2698772/3307066 .
Kopiuję tu kod (ledwo zmodyfikowany). Zasadniczo czyta liczby całkowite, oddzielone od siebie wszystkim, co nie jest cyfrą. (Podziękowania dla oryginalnego autora.)
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;
}
W moim problemie kod ten wynosił ok. 2 razy szybciej niż przy użyciu StringTokenizer
, który był już szybszy niż String.split(" ")
.
(Problem polegał na odczytaniu 1 miliona liczb całkowitych z maksymalnie 1 miliona każda.)Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:30
StringTokenizer
jest o wiele szybszym sposobem odczytu wejść łańcuchowych oddzielonych tokenami.
Sprawdź poniższy przykład, aby odczytać ciąg liczb całkowitych oddzielony spacją i zapisać w 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()));
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-26 08:38:08
Z perspektywy programowania ta dostosowana Klasa Scan i Print jest o wiele lepsza niż wbudowane w Javę klasy Scanner i 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();
}
}
I dostosowana Klasa wydruku może być następująca
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();
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-21 15:33:29
Możesz użyć BufferedReader do odczytu danych
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]);
}
I do drukowania StringBuffer
StringBuffer sb = new StringBuffer();
for(int i=0;i<n;i++){
sb.append(arr[i]+" ");
}
System.out.println(sb);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-14 13:26:31
Oto pełna wersja szybkiego czytelnika i pisarza. Użyłem też buforowania.
import java.io.*;
import java.util.*;
public class FastReader {
private static StringTokenizer st;
private static BufferedReader in;
private static PrintWriter pw;
public static void main(String[] args) throws IOException {
in = new BufferedReader(new InputStreamReader(System.in));
pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
st = new StringTokenizer("");
pw.close();
}
private static int nextInt() throws IOException {
return Integer.parseInt(next());
}
private static long nextLong() throws IOException {
return Long.parseLong(next());
}
private static double nextDouble() throws IOException {
return Double.parseDouble(next());
}
private static String next() throws IOException {
while(!st.hasMoreElements() || st == null){
st = new StringTokenizer(in.readLine());
}
return st.nextToken();
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-02 13:25:08
Odczyt z dysku, raz po raz, powoduje spowolnienie skanera. Lubię używać kombinacji BufferedReader i Scanner, aby uzyskać najlepsze z obu światów. tj. szybkość BufferredReader oraz bogate i łatwe API skanera.
Scanner scanner = new Scanner(new BufferedReader(new InputStreamReader(System.in)));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-26 03:56:02