Ввод с клавиатуры данных разных типов

Всем привет! Учусь работать с ArrayList-ом. Задача такая: добавляем элементы в список, и после того как ввели последний нужный элемент нужно закончить добавление. Решил этот вопрос через цикл while. Но столкнулся с проблемой: Для выхода из цикла нужно нажать какую-то клавишу. В идеале хотел выходом с цикла сделать нажатие пробела(Spacebar), но если я правильно понял по тому, что начитался на просторах интернета - это очень сложно. Так как программа учебная, решил сделать выход через символ(букву). И при выводе на консоль столкнулся с InputMismatchException. Начал пересматривать инфу которую уже знаю и гуглить, но еще больше себя запутал. Может кто подскажет, как обойти это исключение? сделать правильно? или даже прописать выход с цикла с помощью пробела? Спасибо всем, кто подскажет и научит!

    while (true) {
        int number = scan.nextInt();
        list.add(number);
        String out = scan.nextLine().toLowerCase();
        if("i".equals(out)){
            break;
        }
    }
    System.out.println(list);

Это кусок кода. Принцип работы такой: int number принимает наши числа, а когда нам "надоело" их вводить - мы нажимаем клавишу "i", цикл прерывается и в консоль выводит наш list.


Ответы (1 шт):

Автор решения: Nowhere Man

Если стоит задача просто ввести целые числа в список, достаточно придерживаться однородного подхода:

  1. Использовать Scanner::nextInt (+ дополнительно проверять поток ввода Scanner::hasNextInt)
  2. Использовать построчный ввод Scanner::nextLine + Integer.parseInt / Integer.valueOf(String str)

Важно помнить, что по умолчанию разделителями в сканере являются только пробельные символы типа ' ', '\t', '\n'. Если ввод содержит другие разделительные символы, например, знаки пунктуации ',', '.', ';', сканер придётся дополнительно сконфигурировать при помощи метода Scanner::useDelimiter.

Примеры.

  1. Ввод размера списка/массива и последующее заполнение.
    Достаточно использовать только метод Scanner::nextInt:
public static List<Integer> readIntList(Scanner scan) {
    List<Integer> list = new ArrayList<>();
    System.out.println("Введите количество целых чисел: ");
    int n = scan.nextInt();
    System.out.println("Введите " + n + " чисел через пробел");
    while (n-- > 0) {
        list.add(scan.nextInt());
    }
    return list;
}
  1. Ввод списка произвольной длины, пока не будет обнаружено некоторое число -- признак конца ввода (0 для ввода натуральных чисел, -1 -- для ввода неотрицательных чисел и т.п.)
public static List<Integer> readIntList(Scanner scan, int limit) {
    List<Integer> list = new ArrayList<>();
    System.out.println("Вводите целые числа, пока не будет введено число " + limit + " -- признак конца ввода");
    int n;
    while ((n = scan.nextInt()) != limit) {
        list.add(n);
    }
    return list;
}

Как видно, оба метода достаточно просты благодаря тому, что используются одинаковые методы как для ввода основного содержимого списка, так и для ввода "ограничителей".

  1. Ввод списка чисел произвольной длины, пока не будет введена команда выхода (слово или буква)
    Фактически, это исправленный вариант начального кода.
    Для организации выхода будет использоваться особое множество слов Set<String> stopWords.
    Если же пользователь введёт "непонятное" слово или число, они будут проигнорированы.
public static List<Integer> readIntList(Scanner scan, Set<String> stopWords) {
    List<Integer> list = new ArrayList<>();
    System.out.println("Вводите целые числа, пока не будет введено одно из слов: " + stopWords);
    while (true) {
        if (scan.hasNextInt()) {
            list.add(scan.nextInt());
        } else if (scan.hasNext()) {
            if (stopWords.contains(scan.next().toLowerCase())) {
                break;
            }
        }
    }
    return list;
}
  1. Обработка построчного ввода, пока не будет введена пустая строка или же строка, содержащая только пробелы.
    Здесь будет использоваться Scanner::nextLine, для простоты примем, что каждое число вводится в своей строке:
public static List<Integer> readIntListByLine(Scanner scan) {
    List<Integer> list = new ArrayList<>();
    System.out.println("Введите список целых чисел, каждое в своей строке, конец ввода -- пустая строка");
    String line;
    while (!(line = scan.nextLine().trim()).isEmpty()) { // trim() уберёт пробелы
        try {
            list.add(Integer.valueOf(line));
        } catch (NumberFormatException numfex) {
            // numfex.printStackTrace();
        }
    }
    return list;
}

Аналогично можно реализовать проверку на ввод команды для прекращения ввода.

→ Ссылка