В чем смысл использования определенного пользователем класса Scanner для чтения данных на Java?

Этот код взят из конкурса, он отлично работает, если я использую встроенный класс 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;
            }
        }
    }
}

Может конкуренция запрещает использование java.util.Scanner?

Sweeper 16.09.2018 12:13

Этому нет оправдания. StringTokenizer (фактически) устарел.

Boris the Spider 16.09.2018 12:17

@Sweeper, может быть ... Мне просто нужно было, есть ли разница в эффективности кода.

Shakil 16.09.2018 12:36
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
4
3
226
2

Ответы 2

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

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

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

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

Спасибо ... думаю, мне еще предстоит пройти долгий путь.

Shakil 16.09.2018 12:34

Обратите внимание, что вы можете создать Scanner с BufferedReader воспользоваться некоторыми преимуществами BufferedReader - в основном скоростью. Также обратите внимание, что использование synchronized внутри BufferedReader для работы с параллельным вводом-выводом, вероятно, приведет к ужасно неэффективным и, вероятно, неправильному вводу-выводу.

Boris the Spider 17.09.2018 08:47

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

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

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

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


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

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

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

Даже в этом случае это, скорее всего, неверно:

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

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

Если это оптимизированный для производительности код, я бы ожидал увидеть гораздо меньше случайных упаковок / распаковок - и это добавит вашей точке NPE; учитывая количество преобразований из int в Integer и обратно, я могу предположить, что этот код, скорее всего, выбрасывает NPE из самых неожиданных мест.

Boris the Spider 17.09.2018 08:49

Ну да. Но я считаю, что автор >> думает <<, что код более эффективен.

Stephen C 17.09.2018 13:26

Другие вопросы по теме