/
AlexStone
/
Java25sep
Обзор
Документация
Войти
/
AlexStone
/
Java25sep
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
java/tasks 31.html
580 строк
25 KB
unknown
КР 05.11.25
05 ноя 2025, 09:55
05 ноя 2025, 09:55
4a942c9
Код
Авторство
О чём код?
<!DOCTYPE html><html lang="ru"><head><meta charset='utf-8'/><title>31 Реализация стандартных интерфейсов</title><style>.check_single { margin:15px; border:1px solid black; padding:5px; width:calc(100% - 40px); } sqrt val { border-top: 1px solid black; } sqrt:before { content:"\221A"; } .section { counter-reset:section; } .section h3:after { counter-increment:section; content: " " counter(section); } table { border-collapse:collapse; } .check_values, .check_values_v2 { width:100%; counter-reset:test_case; } .check_values td:first-child::before { counter-increment:test_case; content: counter(test_case); } table td, table th { border:1px solid black; text-align:center; } .check_values td:first-child, .check_values_v2 td:first-child{ width:40px; } .check_values td, .check_values_v2 td { max-width: 450px; } .lab_nav ol { list-style:none; } .nav { position:fixed; top:0; right:0; margin:15px; clear:both; } .nav ul{ list-style-type:none; padding:0; float:left; } .nav li { margin:2px; border:1px solid black; } .nav li a { display:block; padding:7px; } .task_block { width:80%; page-break-inside:avoid; padding:10px; display:block; } .task_block:target{ background-color:lightgrey; } .task_block:target .task_id{ color:white; } .task_id { float:right; color:lightgrey; } .quiz_block { width:80%; } .quiz_block:target{ background-color:lightgrey; } .task_desc { margin:5px; } .example_image { width:200px; } .lab_nav { width:80%; overflow:auto; } .check_values .preformatted, .preformatted { font-family:monospace; white-space-collapse:preserve; white-space:pre; text-wrap:pretty; text-align:left; padding:10px; } .stream_values tr td:nth-child(3) { border-top-width:0; border-bottom-width:0; text-align:left; } .stream_values tr:nth-child(2) td:nth-child(2) { border-top-width:0; border-bottom-width:0; text-align:right; } .stream_values tr td:nth-child(1){ border-top-width:0; border-bottom-width:0; text-align:right; } .stream_values tr.test_row td:nth-child(2){ text-align:right; } .stream_values tr td:nth-child(2){ border-top-width:0; border-bottom-width:0; text-align:left; } .stream_values .preformatted{ padding: 0; } .stream_values tr.test_row td { border-top-width:1px; } .stream_values tr.test_row td:first-of-type { border-top-width:1px; border-bottom-width:1px; text-align:center; width:15px; } .stream_values tr:last-of-type td { border-bottom-width:1px; } .stream_values { width:100%; } formula { font-weight:bold; text-align:center; vertical-align:middle; } fraction { display:inline-block; text-align:center; vertical-align:middle; font-weight:bold; } formula .abs{ border-left: solid black 1px; border-right: solid black 1px; padding: 2px; } numerator { display:block; border-bottom:2px solid black; } denominator { display:block; } .comment{ color:darkgrey; } .step{ display:none; } .step:last-child, .step:target{ display:block; } .step:target ~ .step:last-child{ display:none; } .console{ background-color:black; color:white; width:300px; } .zoom{ background-color:lightgrey; font-size:40pt; padding:0 10px; } .task_block:target .zoom { background-color:white; }</style><meta name="author" content="Подборка задач, выбор порядка подачи и подготовка тестовых данных - Крюков Александр, Омск 2013-2019"/></head><body class='section'><a name='heading'><h1>Реализация стандартных интерфейсов</h1></a><div class='lab_nav'>Другие темы<ol> <li>1 <a href='tasks 1.html'>Печать текста на экран</a></li> <li>2 <a href='tasks 2.html'>Заполнение шаблона данными от пользователя</a></li> <li>3 <a href='tasks 3.html'>Организация вычислений</a></li> <li>4 <a href='tasks 4.html'>Проверка исходных данных</a></li> <li>5 <a href='tasks 5.html'>Запуск программы с известными исходными данными</a></li> <li>6 <a href='tasks 6.html'>Взаимоисключающие случаи</a></li> <li>7 <a href='tasks 7.html'>Работа с интервалами значений</a></li> <li>8 <a href='tasks 8.html'>Реорганизация повторяющихся действий</a></li> <li>9 <a href='tasks 9.html'>Обработка неизвестного объема данных</a></li> <li>10 <a href='tasks 10.html'>Вложенные циклы</a></li> <li>11 <a href='tasks 11.html'>Базовые операции с массивами</a></li> <li>12 <a href='tasks 12.html'>Перестановки элементов массива</a></li> <li>13 <a href='tasks 13.html'>Использование числовых массивов</a></li> <li>14 <a href='tasks 14.html'>Вычисление агрегатов</a></li> <li>15 <a href='tasks 15.html'>Поиск в массиве</a></li> <li>16 <a href='tasks 16.html'>Сортировка вставкой</a></li> <li>17 <a href='tasks 17.html'>Строки</a></li> <li>18 <a href='tasks 18.html'>Чтение файлов</a></li> <li>19 <a href='tasks 19.html'>Запись в файлы</a></li> <li>20 <a href='tasks 20.html'>Возврат значения</a></li> <li>21 <a href='tasks 21.html'>Перехват исключений</a></li> <li>22 <a href='tasks 22.html'>Выбрасывание исключений</a></li> <li>23 <a href='tasks 23.html'>Составные типы данных</a></li> <li>24 <a href='tasks 24.html'>Внутреннее состояние</a></li> <li>25 <a href='tasks 25.html'>Коллекции</a></li> <li>26 <a href='tasks 26.html'>Рекурсия</a></li> <li>27 <a href='tasks 27.html'>Даты</a></li> <li>28 <a href='tasks 28.html'>Комбинаторика</a></li> <li>29 <a href='tasks 29.html'>SQL СУБД</a></li> <li>30 <a href='tasks 30.html'>Псевдослучайные числа</a></li> <li>31 <a href='tasks 31.html'>Реализация стандартных интерфейсов</a></li> </ol></div><div class='nav'><ul><li><a href='#heading'>^</a></li><li><a href='#task7020'>1</a><li><a href='#task4043'>2</a><li><a href='#task4248'>3</a><li><a href='#task1658'>4</a><li><a href='#task1533'>5</a></ul></div><div id='task7020' class='task_block'> <div class='task_id'>7020</div> <h3>Задача</h3> <div class='task_desc'> Напишите код класса Countdown, который при вызове метода next будет возвращать числа от N до 0 включительно. Число N должно передаваться в конструкторе. Этот класс должен реализовывать интерфейс Iterator<Integer>. </div> <div class='check_single preformatted'>class Countdown implements Iterator<Integer> {</div> <div class='task_desc'> Интерфейс требует чтобы были реализованы методы: hasNext и next. Эти методы также нужно подписать аннотацией @Override. </div> <div class='check_single preformatted'>@Override public boolean hasNext() { return false; }</div> <div class='check_single preformatted'>@Override public Integer next() { return 0; }</div> <div class='task_desc'> В методе main класса Program добавьте следующий код: </div> <div class='check_single preformatted'>Countdown countdown = new Countdown(5); System.out.println("Первое число должно быть равно 5"); while (countdown.hasNext()) { System.out.print(countdown.next()); System.out.print(" "); } System.out.println("\nПоследнее число должно быть равно 0"); System.out.println("----------"); Countdown countdown2 = new Countdown(0); while (countdown2.hasNext()) { System.out.print(countdown2.next()); System.out.print(" "); } try { System.out.println("\nЕсли следующего элемента нет и мы не проверим hasNext, то будет исключение"); countdown2.next(); System.out.println("Это сообщение не должно быть выведено"); } catch (NoSuchElementException e) { System.out.println("Ожидалось сообщение : Отсутствует следующий элемент"); System.out.println("Фактическое сообщение: " + e.getMessage()); } System.out.println("----------"); try { Countdown countdown3 = new Countdown(-1); System.out.println("Это сообщение не должно быть выведено"); } catch (IllegalArgumentException e) { System.out.println("Ожидалось сообщение : Начальное значение должно быть >= 0"); System.out.println("Фактическое сообщение: " + e.getMessage()); } </div> <div class='task_desc'> В результате запуска программы должно быть выведено сообщение: </div> <div class='check_single preformatted'>Первое число должно быть равно 5 5 4 3 2 1 0 Последнее число должно быть равно 0 ---------- 0 Если следующего элемента нет и мы не проверим hasNext, то будет исключение Ожидалось сообщение : Отсутствует следующий элемент Фактическое сообщение: Отсутствует следующий элемент ---------- Ожидалось сообщение : Начальное значение должно быть >= 0 Фактическое сообщение: Начальное значение должно быть >= 0 </div> </div> <div id='task4043' class='task_block'> <div class='task_id'>4043</div> <h3>Задача</h3> <div class='task_desc'> Реализация интерфейса Iterable позволяет использвать его в цикле for - each. </div> <ol start='1'><li>Убедитесь, что вы реализовали класс Countdown из задачи <a href="tasks 31.html#task7020" target="_blank">ЛР31#7020(открыть в новой вкладке)</a></li><li>Напишите код класса CountdownMaker, который реализует интерфейс Iterable<Integer>.</li><li>В методе iterator() нужно возвращать экземпляр класса Countdown.</li></ol><div class='task_desc'> В методе main класса Program добавьте следующий код: </div> <div class='check_single preformatted'>for (Integer i : new CountdownMaker(5)) { System.out.print(i); System.out.print(" "); } System.out.println("\n---------"); Iterable<Integer> iterable = new CountdownMaker(5); for (Integer i : iterable) {//цикл for - each System.out.print(i); System.out.print(" "); } System.out.println("\nВ отличие от Iterator, класс Iterable можно использовать повторно в новом цикле"); for (Integer i : iterable) {//цикл for - each System.out.print(i); System.out.print(" "); } System.out.println("\n---------"); for (Integer i : new CountdownMaker(0)) { System.out.print(i); System.out.print(" "); } System.out.println("\n---------"); try { iterable = new CountdownMaker(-5); } catch (IllegalArgumentException e) { System.out.println("Ожидалось сообщение : Начальное значение должно быть >= 0"); System.out.println("Фактическое сообщение: " + e.getMessage()); } </div> <div class='task_desc'> В результате запуска программы должно быть выведено сообщение: </div> <div class='check_single preformatted'>5 4 3 2 1 0 --------- 5 4 3 2 1 0 В отличие от Iterator, класс Iterable можно использовать повторно в новом цикле 5 4 3 2 1 0 --------- 0 --------- Ожидалось сообщение : Начальное значение должно быть >= 0 Фактическое сообщение: Начальное значение должно быть >= 0 </div> </div> <div id='task4248' class='task_block'> <div class='task_id'>4248</div> <h3>Задача</h3> <div class='task_desc'> При работе с файлами и консолью используется Scanner. Он реализует интерфейс Closeable. Реализация интерфейса Closeable или AutoCloseable позволяет использовать класс в try-with-resources. </div> <ol start='1'><li>Напишите код класса IncreasingCounter, который реализует интерфейс Iterator<Integer>. При вызове метода next() должно возвращаться целое число, начиная с 0 с шагом 1.</li><li>Класс IncreasingCounter должен реализовывать интерфейс AutoCloseable. После вызова метода close(), метод next() должен выбрасывать исключение IllegalStateException.</li><li>В методе close() нужно вывести сообщение "Вызов метода close"</li></ol><div class='task_desc'> В методе main класса Program добавьте следующий код: </div> <div class='check_single preformatted'>System.out.println("Если просто создать объект, то нужно вручную закрывать"); IncreasingCounter counter = new IncreasingCounter(); int i = 0; while (i < 10) { i = counter.next(); System.out.print(i + " "); } counter.close(); if (counter.hasNext()) { System.out.println("Это сообщение не должно быть напечатано"); } else { System.out.println("Метод hasNext() должен возвращать false после вызова метода close()"); } try { System.out.println("Попытка вызвать метод next() после вызова метода close()"); counter.next(); System.out.println("Это сообщение не должно быть напечатано 2"); } catch (IllegalStateException e) { System.out.println("Ожидалось сообщение : Счётчик завершил работу"); System.out.println("Фактическое сообщение: " + e.getMessage()); } System.out.println("----------"); IncreasingCounter cnt2 = new IncreasingCounter(); System.out.println("чтобы выйти из этого цикла, нужно явно вызвать метод close"); while (cnt2.hasNext()) { i = cnt2.next(); System.out.print(i + " "); //Здесь может быть сложная логика, чтобы определить когда нужно закрыть //Чтобы не отвлекаться на это, используем простое сравнение if (i == 20) { cnt2.close(); } } System.out.println("----------"); int seed = 123456782;//поменяйте это значение, чтобы получить другой случайный результат Random random = new Random(seed); int closeAt = random.nextInt(40); System.out.println(closeAt); IncreasingCounter cnt3 = new IncreasingCounter(); try { i = 0; while (i < 20) { i = cnt3.next(); System.out.print(i + " "); //Здесь может быть сложная логика, в которой может возникнуть исключение //Чтобы не отвлекаться на это, используем простое сравнение if (i == closeAt) { throw new Exception(); } } System.out.println("Исключение может не возникнуть, поэтому нужно закрывать вручную"); cnt3.close(); } catch (Exception e) { System.out.println("Если возникло исключение, то всё равно нужно вручную закрывать"); cnt3.close(); } if (!cnt3.hasNext()) { System.out.println("Закрыто корректно"); } System.out.println("----------"); System.out.println("Использование try-with-resources"); try (IncreasingCounter cnt4 = new IncreasingCounter()) { i = 0; while (i < 20) { i = cnt4.next(); System.out.print(i + " "); //Здесь может быть сложная логика, в которой может возникнуть исключение //Чтобы не отвлекаться на это, используем простое сравнение if (i == closeAt) { throw new Exception(); } } System.out.println("Нормальное завершение"); } catch (Exception e) { System.out.println("Исключение возникло"); } </div> <div class='task_desc'> В результате запуска программы должно быть выведено сообщение: </div> <div class='check_single preformatted'>Если просто создать объект, то нужно вручную закрывать 0 1 2 3 4 5 6 7 8 9 10 Вызов метода close Метод hasNext() должен возвращать false после вызова метода close() Попытка вызвать метод next() после вызова метода close() Ожидалось сообщение : Счётчик завершил работу Фактическое сообщение: Счётчик завершил работу ---------- чтобы выйти из этого цикла, нужно явно вызвать метод close 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Вызов метода close ---------- 22 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Исключение может не возникнуть, поэтому нужно закрывать вручную Вызов метода close Закрыто корректно ---------- Использование try-with-resources 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Нормальное завершение Вызов метода close </div> <div class='task_desc'> Попробуйте изменить значение переменной seed и посмотрите как изменится результат. </div> </div> <div id='task1658' class='task_block'> <div class='task_id'>1658</div> <h3>Задача</h3> <div class='task_desc'> При работе с коллекциями часто используется stream API. Одна из его ключевых операций - преобразование. Напишите код класса StringToDateConverter, который реализует интерфейс Function<String, LocalDate>. Его назначение - преобразовывать String в LocalDate согласно формату yyyy-MM-dd. </div> <div class='task_desc'> В методе main класса Program добавьте следующий код: </div> <div class='check_single preformatted'>List<String> strDates = Arrays.asList( "2023-01-14" , "2024-10-21" , "2025-01-01" , "2025-01-15" , "2025-10-21" ); Function<String, LocalDate> stringToDateConverter = new StringToDateConverter(); List<LocalDate> dates = strDates.stream() .map(stringToDateConverter) .collect(Collectors.toList()); for (LocalDate date : dates) { System.out.print("Год: " + date.getYear()); System.out.print(" Месяц: " + date.getMonthValue()); System.out.println(" День: " + date.getDayOfMonth()); } System.out.println("-------------"); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); //для реализации интерфейса Function в языке Java есть сокращённая запись - lambda-выражение Function<String, LocalDate> converter = date -> LocalDate.parse(date, formatter); List<LocalDate> dates2 = strDates.stream() .map(converter) .collect(Collectors.toList()); for (LocalDate date : dates2) { System.out.print("Год: " + date.getYear()); System.out.print(" Месяц: " + date.getMonthValue()); System.out.println(" День: " + date.getDayOfMonth()); } </div> <div class='task_desc'> В результате запуска программы должно быть выведено сообщение: </div> <div class='check_single preformatted'>Год: 2023 Месяц: 1 День: 14 Год: 2024 Месяц: 10 День: 21 Год: 2025 Месяц: 1 День: 1 Год: 2025 Месяц: 1 День: 15 Год: 2025 Месяц: 10 День: 21 ------------- Год: 2023 Месяц: 1 День: 14 Год: 2024 Месяц: 10 День: 21 Год: 2025 Месяц: 1 День: 1 Год: 2025 Месяц: 1 День: 15 Год: 2025 Месяц: 10 День: 21 </div> </div> <div id='task1533' class='task_block'> <div class='task_id'>1533</div> <h3>Задача</h3> <div class='task_desc'> Вторая по распространённости задача stream API - фильтрация коллекции. Напишите код класса IsJanuaryTest, который реализует интерфейс Predicate<LocalDate>. </div> <ol start='1'><li>Напишите код класса IsJanuaryTest, который реализует интерфейс Predicate<LocalDate>.</li><li>Метод test класса IsJanuaryTest должен возвращать true, если месяц в дате - январm, иначе false.</li><li>Воспользуйтесь методом getMonthValue() класса LocalDate для определения номера месяца.</li><li>Напишите код класса Is2025Test, который реализует интерфейс Predicate<LocalDate>.</li><li>Метод test класса Is2025Test должен возвращать true, если год в дате - 2025, иначе false.</li><li>Воспользуйтесь методом </li></ol><div class='task_desc'> В методе main класса Program добавьте следующий код: </div> <div class='check_single preformatted'>List<String> strDates = Arrays.asList( "2023-01-14" , "2024-10-21" , "2025-01-01" , "2025-01-15" , "2025-10-21" ); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); Predicate<LocalDate> isJanuaryPredicate = new IsJanuaryTest(); List<LocalDate> dates = strDates.stream() .map(date -> LocalDate.parse(date, formatter)) .filter(isJanuaryPredicate) .collect(Collectors.toList()); for (LocalDate date : dates) { System.out.print("Год: " + date.getYear()); System.out.print(" Месяц: " + date.getMonthValue()); System.out.println(" День: " + date.getDayOfMonth()); } System.out.println("-------------"); List<LocalDate> dates2 = strDates.stream() .map(date -> LocalDate.parse(date, formatter)) .filter(new Is2025Test()) .collect(Collectors.toList()); for (LocalDate date : dates2) { System.out.print("Год: " + date.getYear()); System.out.print(" Месяц: " + date.getMonthValue()); System.out.println(" День: " + date.getDayOfMonth()); } System.out.println("-------------"); List<LocalDate> dates3 = strDates.stream() .map(date -> LocalDate.parse(date, formatter)) //сокращённая запись с помощью lambda-выражения .filter(date -> date.getDayOfMonth() == 21) .collect(Collectors.toList()); for (LocalDate date : dates3) { System.out.print("Год: " + date.getYear()); System.out.print(" Месяц: " + date.getMonthValue()); System.out.println(" День: " + date.getDayOfMonth()); } </div> <div class='task_desc'> В результате запуска программы должно быть выведено сообщение: </div> <div class='check_single preformatted'>Год: 2023 Месяц: 1 День: 14 Год: 2025 Месяц: 1 День: 1 Год: 2025 Месяц: 1 День: 15 ------------- Год: 2025 Месяц: 1 День: 1 Год: 2025 Месяц: 1 День: 15 Год: 2025 Месяц: 10 День: 21 ------------- Год: 2024 Месяц: 10 День: 21 Год: 2025 Месяц: 10 День: 21 </div> </div> Версия 20240202. Подборка задач, выбор порядка подачи и подготовка тестовых данных - Крюков Александр, Омск 2013-2026. <a href='https://github.com/AKryukov92/programming-basics'>Основной репозиторий</a></body></html>