Какой смысл использовать пользовательский класс Scanner для чтения данных в Java? - PullRequest
0 голосов
/ 16 сентября 2018

Этот код с соревнования, он отлично работает, если я использую встроенный класс Scanner для чтения данных. Но здесь, в этом оригинальном решении, они определили собственный класс MyScanner для чтения данных? Это почему? Это как-то связано со временем выполнения или есть какая-то другая цель? Будем благодарны за любое разумное объяснение или ссылку на соответствующую концепцию, заранее.

class Main {
    final static int[] coins = {50, 25, 10, 5, 1};
    static int[][] memo;
    public static void main(String[] args) throws IOException{
        MyScanner sc = new MyScanner();
        Integer num = 7489 + 1;
        memo = new int[num+1][coins.length];
        for (int i = 0; i < num+1; i++) {
           Arrays.fill(memo[i], -1);
        }
        while ((num = sc.nextInt()) != null) {
            int r = change(num, 0);
            System.out.println(r);
        }
    }

    private static int change(int num, int cInd) {
        if (num < 0){
            return 0;
        } else if (num == 0 || cInd == coins.length-1){
            return 1;
        } else if(memo[num][cInd] != -1) {
            return memo[num][cInd];
        }else {
            int result = change(num, cInd+1) + change(num-coins[cInd], cInd);
            return memo[num][cInd] = result;
        }
    }

    static class MyScanner {
        BufferedReader br;
        StringTokenizer st;
        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }
        public String next() throws IOException {
            if (st == null || !st.hasMoreTokens()) {
                String line = br.readLine();
                if (line == null){
                    return null;
                }
                st = new StringTokenizer(line);
            }
            return st.nextToken();
        }
        public Integer nextInt() throws IOException {
            String next = next();
            if (next != null) {
                return Integer.parseInt(next);
            } else {
                return null;
            }
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 16 сентября 2018

В соревнованиях по программированию одним из критериев соревнования может быть то, насколько быстро код участника может обработать какой-либо текстовый входной файл. Обычно вы увидите, что такие вещи (класс MyScanner) используются, потому что разработчик считает, что это дает ему или ей "преимущество" в производительности по сравнению со стандартными классами. Люди, которые «увлекаются» конкурентным программированием, разработают свои собственные наборы инструментов ... чтобы улучшить свои преимущества.

Не ясно, будет ли этот класс действительно работать лучше в целом , или будет ли вклад в общую производительность значительным. Нужно было бы:

  1. написать несколько общих тестов и
  2. профилировать решение проблемы конкуренции.

Но в каком-то смысле это не имеет значения. Что действительно важно, так это то, что человек, который использует этот код , считает, лучше. В любом случае, он делает то, что они считают необходимым. Цели оправдывают средства.


С другой стороны, если бы вы делали подобные вещи в производственном коде, вы, вероятно, оказали бы медвежью услугу вашему проекту / работодателю:

  1. Маловероятно, что подобные вещи помогут в реальных приложениях.
  2. Вы бы добавили техническую нагрузку в виде ненужного / возможно ненадежного кода для ваших коллег / преемников.

Вы должны прибегать к подобным вещам, только если профилирование вашего приложения показывает, что сканирование является существенным узким местом производительности.

Даже тогда подобные вещи, скорее всего, неправильны:

        if (next != null) {
            return Integer.parseInt(next);
        } else {
            return null;
        }

, поскольку он может быть источником неожиданных NPE.

0 голосов
/ 16 сентября 2018

Правильный вопрос, который нужно здесь задать, - это Scanner vs Buffered Reader, поскольку решение основано на BufferedReader.Вы можете читать дальше здесь.

Сканер против BufferedReader

Надеюсь, это будет полезно.Вот мои 2 цента

  • BufferedReader работает синхронно, а сканер - нет.BufferedReader
    следует использовать, если мы работаем с несколькими потоками.
  • BufferedReader имеет значительно большую буферную память, чем Scanner.
  • Сканер имеет небольшой буфер (1KB буфер символов) в отличие отBufferedReader (8KB байтовый буфер), но этого более чем достаточно.
  • BufferedReader немного быстрее по сравнению со сканером, поскольку сканер выполняет синтаксический анализ входных данных, а BufferedReader просто читает последовательность символов.
...