有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java更有效地从控制台读取int值

如何从控制台(从内存)更高效地读取int值

BufferedReader in ...
number = Integer.parseInt(in.readLine());

当我使用readLine()并将其解析为int时,java会创建许多字符串对象并占用内存。我尝试使用Scanner和方法nextInt(),但这种方法也没有那么有效

P.S I need read > 1000_000 values and I have memory limit.

编辑任务的完整代码

import java.io.*;

public class Duplicate {

    public static void main(String[] args) throws IOException {

        int last = 0;
        boolean b = false;

        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        int n = Integer.parseInt(reader.readLine());

        for (int i = 0; i < n; i++) {
            int number =Integer.parseInt(reader.readLine());
            if (number == 0 && !b) {
                System.out.println(0);
                b = true;
            }
            if (number == last) continue;
            last = number;
            System.out.print(last);
        }
    }
}

并重写变体:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;

public class Duplicate {

    public static void main(String[] args) throws IOException {

        int last = 0;
        boolean b = false;

        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        int nextInt = getNextInt(reader);

        for (int i = 0; i < nextInt; i++) {
            int number = getNextInt(reader);
            if (number == 0 && !b) {
                System.out.println(0);
                b = true;
            }
            if (number == last) continue;
            b = true;
            last = number;
            System.out.println(last);
        }
    }

    static int getNextInt(Reader in) throws IOException {
        int c;
        boolean negative = false;
        do {
            c = in.read();
            if (!Character.isDigit(c)) {
                negative = c == '-';
            }
        } while (c != -1 && !Character.isDigit(c));
        if (c == -1) return Integer.MIN_VALUE;

        int num = Character.getNumericValue(c);
        while ((c = in.read()) != -1 && Character.isDigit(c)) {
            num = 10 * num + Character.getNumericValue(c);
        }
        return negative ? -num : num;
    }
}

这两个选项都不会从内存中传递(((

enter image description here

EDIT2我尝试分析

int number = getRandom();并从1000000开始

enter image description here

再次推出同样的产品 enter image description here

和飞溅GC

enter image description here


共 (3) 个答案

  1. # 1 楼答案

    您可以使用这个FastScanner

    static class FastScanner {
        private BufferedReader reader = null;
        private StringTokenizer tokenizer = null;
    
        public FastScanner(InputStream in) {
            reader = new BufferedReader(new InputStreamReader(in));
            tokenizer = null;
        }
    
        public String next() {
            if (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }
    
        public String nextLine() {
            if (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    return reader.readLine();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
    
            return tokenizer.nextToken("\n");
        }
    
        public long nextLong() {
            return Long.parseLong(next());
        }
    
        public int nextInt() {
            return Integer.parseInt(next());
        }
    }
    

    codeforces上非常常用于读取大输入,其中Scanner类导致TLE

    这本书的作者是https://codeforces.com/profile/Petr

  2. # 2 楼答案

    你可以一次读取一个字符,检查它是否是一个数字,然后把它累加成一个数字。比如:

    int getNextInt(Reader in) throws IOException {
      int c;
      boolean negative = false;
      do {
        c = in.read();
        if (!Character.isDigit(c)) { negative = c == '-' };
      } while (c != -1 && !Character.isDigit(c));
      if (c == -1) return Integer.MIN_VALUE;  // Some sentinel to indicate nothing found.
    
      int num = Character.getNumericValue(c);
      while ((c = in.read()) != -1 && Character.isDigit(c)) {
        num = 10 * num + Character.getNumericValue(c);
      }
      return negative ? -num : num;
    }
    

    Ideone demo

    当然,这是难以置信的原始解析。但您可能可以将此代码作为基础,并根据需要对其进行修改

  3. # 3 楼答案

    我在^{上使用这个InputReader。对我来说,在大型输入案例中效果很好。您可以将其扩展到您的用例。我是在使用Scanner获得TLE并在需要时添加功能后遇到这个问题的

    static class InputReader {
        private final InputStream stream;
        private final byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
    
        public InputReader(InputStream stream) {
            this.stream = stream;
        }
    
        private int read() {
            try {
                if (curChar >= numChars) {
                    curChar = 0;
                    numChars = stream.read(buf);
                    if (numChars <= 0)
                        return -1;
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return buf[curChar++];
        }
    
        public int readInt() {
            return (int) readLong();
        }
    
        public long readLong() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
                if (c == -1) throw new RuntimeException();
            }
            boolean negative = false;
            if (c == '-') {
                negative = true;
                c = read();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9') throw new InputMismatchException();
                res *= 10;
                res += (c - '0');
                c = read();
            } while (!isSpaceChar(c));
            return negative ? (-res) : (res);
        }
    
        public int[] readIntArray(int size) {
            int[] arr = new int[size];
            for (int i = 0; i < size; i++) arr[i] = readInt();
            return arr;
        }
    
        private boolean isSpaceChar(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }
    
    }