Коллекции

  1. Создать список List<String> из чисел от 1 до 100. Здесь и везде реализуйте функцию, которая решает задачу. В main методе вызовите ее для проверки.
  2. Дан список, верните новый список, в котором все элементы идут в обратном порядке. Сделайте две версии задачи: чистую функцию и функцию, которая меняет заданный список.
  3. Сделайте по две версии следующих трех функций: чистую функцию и функцию, которая меняет заданный список.
    • Дан List<String>, удалите в нем все элементы с четным индексом.
    • Дан List<String>, удалить в нем все элементы, которые являются четными числами
    • Дан List<Integer>, удалить в нем все элементы, которые являются четными числами
  4. Взять текстовый файл, желательно большой на русском. Прочитать из него все слова, каждое слово привести к нижнему регистру и сохранить в множестве HashSet. Вывести все слова.
    • Повторите аналогичные действия для TreeSet, LinkedHashSet. Т.е. Ваша программа должна читать текстовый файл три раза. Убедитесь, что вы не дублируете код, и не скопировали программу три раза для каждого из видов множества.

Ассоциативные массивы

  1. Дана строка. Посчитать каждый символ, сколько раз он встретился. Например, строка “banana” должна выдать массив Map<Character, Integer>:

         'b' -> 1
         'a' -> 3
         'n' -> 2
    
  2. Аналогично предыдущему, но выдать Map<Character, List<Integer>> со списком индексов, где встретился символ:

         b -> [0]
         a -> [1, 3, 5]
         n -> [2, 4]
    
  3. Частотный словарь слов из файла. Т.е. нужно прочитать слова из файла и посчитать, сколько раз они встретились. Приводите слова к нижнему регистру перед подсчетом. Желательно использовать большой текст на русском, например, возьмите его на http://lib.ru. Используйте Scanner.useDelimiter(), чтобы указать сканеру, какие символы считать разделителями слов.

    • Сначала используйте HashMap
    • Потом исправьте программу так, чтобы она использовала все три вида массивов: HashMap, TreeMap, LinkedHashMap. Соответственно, выведите ответ три раза. Не дублируйте код.
    • Выведите слова в порядке уменьшения частот. Вам потребуется отсортировать список List<Map.Entry<String, Integer»

Объектно-ориентированное программирование

Рациональные числа

Рациональные числа

Рисование

Класс Drawing (изображение) хранит изображение в виде массива символов char[][]. Например,

    .........
    .........
    ....x....
    .........
  1. Создайте конструктор, в котором указывается размер (сколько строк и столбцов) и символ, которым изначально все заполнить. Например, new Drawing(20, 30, ‘.’)
  2. Создайте метод print(), он печатает на экране изображение
  3. Метод setPoint(x, y, char) рисует один символ в изображении. Методу нужно указать, где и какой символ поставить.
  4. Методы drawVerticalLine(...), drawHorizontalLine(...) рисуют вертикальную или горизонтальную линию от заданной точки до заданной. Определите сами параметры для методов, они должны определять расположение линии и символ, которым линию рисовать.
  5. Метод drawRectangle() рисует прямоугольник по двум противоположным углам, стороны прямоугольника вертикальны и горизонтальны. Используйте методы, реализованные ранее.
  6. Необязательно: Рисование произвольной линии (см. необязательную задачу за прошлый семестр)
  7. Рисование круга (или окружности — необязательно). Пользователь указывает центр и радиус, программа должна пройтись по всем точкам поля и, если они лежат в круге, зарисовать их указанным символом.
  8. Реализуйте метод draw(x, y, Drawing d) нарисовать одно изображение на другом. При вызове метода указывается, где и какое изображение рисовать.
  9. (Необязательная задача). Сделайте Drawing неизменяемым: все функции рисования возвращают новый Drawing и не меняют текущий.
  10. Используйте все реализованные вами ранее методы, чтобы нарисовать домик.

Наследование

Создайте класс Figure, который означает геометрическую фигуру. По ходу решения постоянно пишите код, который проверяет работоспособность всех реализованных функций.

  1. Добавьте класс методы double area() и double perimiter(), которые возвращают, соответственно, площадь и периметр фигуры. Если вы уже знаете абстрактные методы, сделайте их абстрактными. Иначе пусть методы возвращают 0.
  2. Добавьте метод String type() для указания типа фигуры. Там будет возвращаться текст типа “квадрат”, “круг” и т.п. В классе Figure метод возвращает null
  3. Добавьте метод public String toString(), который печатает текст типа “Я фигура квадрат площади 4 и периметра 8”. Он использует методы area(), perimiter(), type().
  4. Добавьте классы круг, квадрат, прямоугольник, равносторонний треугольник. Они должны наследовать класс Figure и переопределять все необходимые методы. В конструкторы классов должны передаваться размеры: ширина и высота для прямоугольника, сторона для квадрата, радиус для круга, сторона для равностороннего треугольника.
  5. Кого от кого унаследовать, прямоугольник от квадрата или квадрат от прямоугольника?

Интерфейсы, лямбда выражения и анонимные классы

  1. Создайте интерфейс Printable с одним методом void print(), этот метод означает что объект печатает что-то на экране. Сделайте так, что класс Drawing реализует этот интерфейс. Проверьте, что получилось.
  2. Создайте класс PrintableLetter, реализующий интерфейс Printable. Пользоваться классом нужно так:

       PrintableLetter pl = new PrintableLetter("x", 10);
       pl.print(); //печатает букву x 10 раз
    
  3. Создайте класс PrintableString, реализующий интерфейс Printable, этот класс хранит строку, пользоваться им нужно так:

       PrintableString ps = new PrintableString("asdf");
       ps.print(); //печатает asdf
    
  4. Создайте массив типа Printable[], заполните его 1) Drawing 2) PrintableLetter 3) PrintableString 4) анонимным классом 5) лямбда выражением. В цикле попросите всех что-нибудь напечатать.

Потоки (Streams)

Следующая функция возвращает бесконечный поток случайных целых чисел от 0 до max - 1. Попробуйте понять, как она работает.

    public static IntStream randomStream(int max) {
        Random r = new Random();
        return IntStream.generate(() -> r.nextInt(max));
    }

Следующая функция возвращает бесконечный поток натуральных чисел 1, 2, 3 и т.д. Попробуйте понять, как она работает

    public static IntStream integersStream() {
        return IntStream.iterate(1, x -> x + 1);
    }

Используйте метод Scanner.tokens() для получения потока слов из файла.

Во всех следующих задачах используйте потоки. Создавайте их сами из коллекций, или пользуйтесь приведенными выше функциями.

  1. Дано n. Посчитайте сумму
    1. чисел от 1 до n
    2. квадратов чисел от 1 до n
    3. кубов чисел от 1 до n
    4. обратных чисел от 1 до n
  2. Дан список чисел. Верните новый список, в котором удалены все четные числа.
  3. Дан файл. Посчитайте среднюю длину слов в этом файле. А еще максимальные и минимальные длины слов. Используйте подходящий Collector.
    1. Найдите самое длинное слово в файле. Получится сделать это за один проход по потоку?
  4. Бросьте монетку 100 раз, сколько раз выпал орёл, а сколько решка?
  5. Посчитайте количество слов в потоке.
  6. Сколько в тексте слов, начинающихся с заглавной буквы?
  7. Посчитайте количество слов в потоке без учета стоп-слов. Приводите слова к нижнему регистру для сравнения со стоп словами.

    Подсказка: создайте Set для списка стоп-слов.

  8. Какая средняя длина слова в вашем тексте?
  9. Посчитайте сразу и среднюю длину слова, и максимальная длину, и минимальную. Подсказка: для вычисления сразу всех статистик есть соответствующий Collector.
  10. Каких слов больше, с четной длиной или с нечетной длиной? Попробуйте сделать только один проход по потоку для получения ответа.
  11. Распечатайте «табличку», сколько раз встретилась каждая длина слова. Например, слов длины 1: 10 штук, слов длины 2: 40 штук и т.п.
  12. Аналогично предыдущей задаче, но должно быть две таблички. С учетом одинаковых слов или без учета одинаковых слов. Т.е. Если некоторое слово встретилось дважды, его нужно считать дваждый в первой таблице, и один раз во второй таблице.
  13. Посчитайте частоты всех слов файла. Верните Map<String, Integer>, сопоставляющий каждому слову количество раз, которое оно встретилось в файле. Приводите слова к нижнему регистру.
  14. Получите частоты всех слов в файле с помощью предыдущей задачи и выведите слова в порядке убывания частот. Подсказка. У Map есть метод entrySet который возвращает множество (Set) записей, содержащих пару из ключа и значения. С этим множеством тоже можно работать с помощью потоков, и сортировать его.
  15. Пусть S = количество стоп-слов. Если взять первые S самых частотных слов вашего текста, сколько совпадений будет со словами стоп-листа?
  16. Сложно. Определите имена в тексте. Имена — это слова, начинающиеся с заглавной буквы, перед которыми не было конца предложения, т.е. точки, восклицательного знака, вопросительного знака.
  17. Сложно. Создайте класс Context. Он содержит String word — слово и Set<String> — несколько соседних слов, пять до и пять после. (5 — это константа, которую можно менять при создании класса). Превратите поток слов в поток их контекстов.

Обработка исключений

  1. Реализуйте функцию, int readInt(String message), которая выводит на экран указанное сообщение и читает с клавиатуры число, которое вводит пользователь. Если пользователь вводит не число, требуется сказать ему, что введено не число и снова потребовать ввод.

    Для чтения с клавиатуры создайте сканер new Scanner(System.in). Обратите внимание, что закрывать такой сканер не нужно.

    Такую задачу правильно было бы решать, используя функцию сканнера hasNextInt(), чтобы определить, ввел пользователь число или нет. Но я предлагаю делать иначе, чтобы разобраться с обработкой исключений.

    Читайте введенное пользователем слово с помощью метода next(). Вызывайте Integer.parseInt(), чтобы превратить строку в число. Посмотрите в помощи, какое исключение генерирует Integer.parseInt(), если строка числом не является, и обработайте это исключение.

  2. Реализуйте функцию void hateOdds(int n), которая ничего не делает, если получает четное число, и генерирует исключение Exception, если нечетное. После этого напишите программу (в функции, естественно, как и все наши программы), которая перебирает числа от 1 до 10 и для каждого пишет, вызвала ли функция hateOdds() исключение.

Equals и HashCode

Необязательный блок для скучающих.

  1. Вспомните задачу про фигуры, и добавьте в каждую фигуру методы equals() и hashCode(). Проверьте, что этими фигурами можно пользоваться в Map<,>.