Домашнее задание 1. Обход файлов-
Разработайте класс Walk, осуществляющий подсчет хеш-сумм файлов.
-
Формат запуска:
java Walk <входной файл> <выходной файл> -
Входной файл содержит список файлов, которые требуется обойти.
-
Выходной файл должен содержать по одной строке для каждого файла.
Формат строки:
<шестнадцатеричная хеш-сумма> <путь к файлу> -
Для подсчета хеш-суммы используйте
алгоритм SHA-1
(поддержка есть в стандартной библиотеке).
-
Если при чтении файла возникают ошибки, укажите в качестве
его хеш-суммы 40 нулей.
-
Кодировка входного и выходного файлов — UTF-8.
-
Если родительская директория выходного файла
не существует, то соответствующий путь надо создать.
-
Размеры файлов могут превышать размер оперативной памяти.
-
Пример
Входной файл |
---|
samples/1
samples/12
samples/123
samples/1234
samples/1
samples/binary
samples/no-such-file
| Выходной файл |
---|
356a192b7913b04c54574d18c28d46e6395428ab samples/1
7b52009b64fd0a2a49e6d8a939753077792b0554 samples/12
40bd001563085fc35165329ea1ff5c5ecbdbbeef samples/123
7110eda4d09e062aa5e4a390b0a572ac0d2c0220 samples/1234
356a192b7913b04c54574d18c28d46e6395428ab samples/1
4916d6bdb7f78e6803698cab32d1586ea457dfc8 samples/binary
0000000000000000000000000000000000000000 samples/no-such-file
|
-
Сложный вариант:
-
Разработайте класс RecursiveWalk,
осуществляющий подсчет хеш-сумм файлов в
директориях.
-
Входной файл содержит список файлов и директорий,
которые требуется обойти. Обход директорий осуществляется
рекурсивно.
-
Пример:
Входной файл |
---|
samples/binary
samples
samples/no-such-file
| Выходной файл |
---|
4916d6bdb7f78e6803698cab32d1586ea457dfc8 samples/binary
356a192b7913b04c54574d18c28d46e6395428ab samples/1
7b52009b64fd0a2a49e6d8a939753077792b0554 samples/12
40bd001563085fc35165329ea1ff5c5ecbdbbeef samples/123
7110eda4d09e062aa5e4a390b0a572ac0d2c0220 samples/1234
4916d6bdb7f78e6803698cab32d1586ea457dfc8 samples/binary
0000000000000000000000000000000000000000 samples/no-such-file
|
-
При выполнении задания следует обратить внимание на:
-
Дизайн и обработку исключений, диагностику ошибок.
-
Программа должна корректно завершаться даже в случае ошибки.
-
Корректная работа с вводом-выводом.
-
Отсутствие утечки ресурсов.
-
Требования к оформлению задания.
-
Проверяется исходный код задания.
-
Весь код должен находиться в пакете
info.kgeorgiy.ja.фамилия.walk.
Репозиторий курса Домашнее задание 2. Множество на массиве-
Разработайте класс
ArraySet ,
реализующий неизменяемое упорядоченное множество.
-
Класс
ArraySet должен реализовывать
интерфейс
SortedSet
(простой вариант)
или
NavigableSet
(сложный вариант).
-
Все операции над множествами должны производиться с максимально возможной асимптотической эффективностью.
-
При выполнении задания следует обратить внимание на:
-
Применение стандартных коллекций.
-
Избавление от повторяющегося кода.
Домашнее задание 3. Студенты-
Разработайте класс
StudentDB ,
осуществляющий поиск по базе данных студентов.
-
Класс
StudentDB должен реализовывать
интерфейс StudentQuery (простой вариант)
или GroupQuery (сложный вариант).
-
Каждый метод должен состоять из ровно одного оператора.
При этом длинные операторы надо разбивать на несколько строк.
-
При выполнении задания следует обратить внимание на:
-
применение лямбда-выражений и потоков;
-
избавление от повторяющегося кода.
Домашнее задание 4. Implementor-
Реализуйте класс
Implementor ,
генерирующий реализации классов и интерфейсов.
-
Аргумент командной строки: полное имя класса/интерфейса, для
которого требуется сгенерировать реализацию.
-
В результате работы должен быть сгенерирован java-код класса с суффиксом
Impl , расширяющий (реализующий) указанный класс (интерфейс).
-
Сгенерированный класс должен компилироваться без ошибок.
-
Сгенерированный класс не должен быть абстрактным.
-
Методы сгенерированного класса должны игнорировать свои аргументы и
возвращать значения по умолчанию.
-
В задании выделяются три варианта:
- Простой —
Implementor должен уметь реализовывать
только интерфейсы (но не классы). Поддержка generics не требуется.
- Сложный —
Implementor должен уметь реализовывать
и классы, и интерфейсы. Поддержка generics не требуется.
- Бонусный —
Implementor должен уметь реализовывать
generic-классы и интерфейсы. Сгенерированный код должен иметь
корректные параметры типов и не порождать UncheckedWarning .
-
Jar
-
Модифицируйте
Implementor так, чтобы
при запуске с аргументами -jar имя-класса файл.jar
он генерировал .jar -файл с реализацией
соответствующего класса (интерфейса).
Для компиляции используйте код из тестов.
-
Создайте
.jar -файл, содержащий скомпилированный
Implementor и сопутствующие классы.
-
Созданный
.jar -файл должен запускаться командой
java -jar .
-
Запускаемый
.jar -файл должен принимать те же аргументы командной
строки, что и класс Implementor .
-
Для проверки, кроме исходного кода, также должны быть представлены:
-
скрипт для создания запускаемого
.jar -файла,
в том числе, исходный код манифеста;
-
запускаемый
.jar -файл.
- Сложный вариант. Решение должно быть модуляризовано.
-
Javadoc
-
Документируйте класс
Implementor и сопутствующие классы
с применением Javadoc.
-
Должны быть документированы все классы и все члены классов,
в том числе
private .
-
Документация должна генерироваться без предупреждений.
-
Сгенерированная документация должна содержать корректные
ссылки на классы стандартной библиотеки.
-
Для проверки, кроме исходного кода, также должны быть представлены:
-
скрипт для генерации документации
(он может рассчитывать, что рядом с вашим репозиторием
склонирован репозиторий курса);
-
сгенерированная документация.
-
Это домашнее задание связано с предыдущим.
Предыдущее домашнее задание отдельно сдать будет нельзя.
-
В последующих домашних заданиях все
public и
protected сущности должны быть документированы.
Домашнее задание 6. Итеративный параллелизм-
Реализуйте класс IterativeParallelism,
который будет обрабатывать списки в несколько потоков.
-
В простом варианте должны быть реализованы следующие методы:
- minimum(threads, list, comparator) —
первый минимум;
- maximum(threads, list, comparator) —
первый максимум;
- all(threads, list, predicate) —
проверка, что все элементы списка, удовлетворяют предикату;
- any(threads, list, predicate) —
проверка, что существует элемент списка, удовлетворяющий предикату.
-
В сложном варианте должны быть дополнительно реализованы следующие методы:
- filter(threads, list, predicate) —
вернуть список, содержащий элементы удовлетворяющие предикату;
- map(threads, list, function) —
вернуть список, содержащий результаты применения функции;
- join(threads, list) —
конкатенация строковых представлений элементов списка.
-
Во все функции передается параметр threads —
сколько потоков надо использовать при вычислении.
Вы можете рассчитывать, что число потоков относительно мало.
-
Не следует рассчитывать на то, что переданные компараторы,
предикаты и функции работают быстро.
-
При выполнении задания нельзя использовать
Concurrency Utilities.
-
Рекомендуется подумать, какое отношение к
заданию имеют моноиды.
Домашнее задание 7. Параллельный запуск-
Напишите класс ParallelMapperImpl, реализующий интерфейс
ParallelMapper.
public interface ParallelMapper extends AutoCloseable {
<T, R> List<R> map(
Function<? super T, ? extends R> f,
List<? extends T> args
) throws InterruptedException;
@Override
void close();
}
-
Метод run должен параллельно вычислять
функцию f на каждом из указанных аргументов
(args).
-
Метод close должен останавливать все рабочие потоки.
-
Конструктор ParallelMapperImpl(int threads)
создает threads рабочих потоков, которые могут
быть использованы для распараллеливания.
-
К одному ParallelMapperImpl могут одновременно обращаться
несколько клиентов.
-
Задания на исполнение должны накапливаться в очереди и обрабатываться
в порядке поступления.
-
В реализации не должно быть активных ожиданий.
-
Доработайте класс IterativeParallelism так,
чтобы он мог использовать ParallelMapper.
-
Добавьте конструктор IterativeParallelism(ParallelMapper)
-
Методы класса должны делить работу на threads
фрагментов и исполнять их при помощи ParallelMapper.
-
При наличии ParallelMapper сам
IterativeParallelism новые потоки создавать не должен.
-
Должна быть возможность одновременного запуска и работы
нескольких клиентов, использующих один ParallelMapper.
Домашнее задание 8. Web Crawler-
Напишите потокобезопасный класс
WebCrawler , который
будет рекурсивно обходить сайты.
-
Класс
WebCrawler должен иметь конструктор
public WebCrawler(Downloader downloader, int downloaders, int extractors, int perHost)
downloader позволяет скачивать страницы и
извлекать из них ссылки;
downloaders — максимальное число
одновременно загружаемых страниц;
extractors — максимальное число страниц,
из которых одновременно извлекаются ссылки;
perHost — максимальное число страниц,
одновременно загружаемых c одного хоста.
Для определения хоста следует использовать
метод getHost класса
URLUtils из тестов.
-
Класс
WebCrawler должен реализовывать интерфейс
Crawler
public interface Crawler extends AutoCloseable {
Result download(String url, int depth);
void close();
}
-
Метод
download должен
рекурсивно обходить страницы, начиная с указанного URL,
на указанную глубину и возвращать
список загруженных страниц и файлов.
Например, если глубина равна 1, то должна быть
загружена только указанная страница. Если глубина равна
2, то указанная страница и те страницы и файлы, на которые
она ссылается, и так далее.
Этот метод может вызываться параллельно в нескольких потоках.
-
Загрузка и обработка страниц (извлечение ссылок)
должна выполняться максимально параллельно,
с учетом ограничений на число одновременно
загружаемых страниц (в том числе с одного хоста)
и страниц, с которых загружаются ссылки.
-
Для распараллеливания разрешается создать
до
downloaders + extractors
вспомогательных потоков.
-
Загружать и/или извлекать ссылки из одной
и той же страницы в рамках одного обхода
(
download ) запрещается.
-
Метод
close должен завершать все
вспомогательные потоки.
-
Для загрузки страниц должен применяться
Downloader ,
передаваемый первым аргументом конструктора.
public interface Downloader {
public Document download(final String url) throws IOException;
}
-
Должен быть реализован метод
main ,
позволяющий запустить обход из командной строки
-
Версии задания
- Простая — не требуется учитывать ограничения
на число одновременных закачек с одного хоста
(
perHost >= downloaders ).
- Полная — требуется учитывать все ограничения.
- Бонусная — сделать параллельный обход в ширину.
-
Задание подразумевает активное использование Concurrency Utilities,
в частности, в решении не должно быть «велосипедов»,
аналогичных/легко сводящихся к классам из Concurrency Utilities.
Домашнее задание 9. HelloUDP-
Реализуйте клиент и сервер, взаимодействующие по UDP.
-
Класс HelloUDPClient должен отправлять запросы
на сервер, принимать результаты и выводить их на консоль.
-
Аргументы командной строки:
- имя или ip-адрес компьютера, на котором запущен сервер;
- номер порта, на который отсылать запросы;
- префикс запросов (строка);
- число параллельных потоков запросов;
- число запросов в каждом потоке.
-
Запросы должны одновременно отсылаться в указанном числе потоков.
Каждый поток должен ожидать обработки своего запроса и выводить
сам запрос и результат его обработки на консоль.
Если запрос не был обработан, требуется послать его заново.
-
Запросы должны формироваться по схеме
<префикс запросов><номер потока>_<номер запроса в потоке>.
-
Класс HelloUDPServer должен принимать задания, отсылаемые
классом HelloUDPClient и отвечать на них.
-
Аргументы командной строки:
- номер порта, по которому будут приниматься запросы;
- число рабочих потоков, которые будут обрабатывать запросы.
-
Ответом на запрос должно быть Hello, <текст запроса>.
-
Несмотря на то, что текущий способ получения ответа по запросу
очень прост, сервер должен быть рассчитан на ситуацию,
когда этот процесс может требовать много ресурсов и времени.
-
Если сервер не успевает обрабатывать запросы, прием запросов может
быть временно приостановлен.
Домашнее задание 10. Физические лица-
Добавьте к банковскому приложению возможность работы с физическими
лицами.
-
У физического лица (
Person ) можно запросить
имя, фамилию и номер паспорта.
-
Удалённые физические лица (
RemotePerson )
должны передаваться при помощи удалённых объектов.
-
Локальные физические лица (
LocalPerson )
должны передаваться при помощи механизма сериализации,
и при последующем использовании не требовать связи с сервером.
-
Должна быть возможность поиска физического лица по
номеру паспорта, с выбором типа возвращаемого лица.
-
Должна быть возможность создания записи о физическом лице
по его данным.
-
У физического лица может быть несколько счетов,
к которым должен предоставляться доступ.
-
Счету физического лица с идентификатором subId
должен соответствовать банковский счет с id
вида passport:subId.
-
Изменения, производимые со счетом в банке
(создание и изменение баланса), должны быть видны всем
соответствующим
RemotePerson ,
и только тем LocalPerson ,
которые были созданы после этого изменения.
-
Изменения в счетах, производимые через
RemotePerson ,
должны сразу применяться глобально, а производимые
через LocalPerson – только локально
для этого конкретного LocalPerson .
-
Реализуйте приложение, демонстрирующее работу с физическим лицами.
-
Аргументы командной строки: имя, фамилия, номер паспорта физического
лица, номер счета, изменение суммы счета.
-
Если информация об указанном физическом лице отсутствует, то оно должно
быть добавлено. В противном случае – должны быть проверены его данные.
-
Если у физического лица отсутствует счет с указанным номером, то
он создается с нулевым балансом.
-
После обновления суммы счета новый баланс должен выводиться на консоль.
-
Напишите тесты, проверяющие вышеуказанное поведение как банка, так и приложения.
-
Для реализации тестов рекомендуется использовать
JUnit
(Tutorial).
Множество примеров использования можно найти в тестах.
-
Если вы знакомы с другим тестовым фреймворком
(например, TestNG),
то можете использовать его.
-
Jar-файлы используемых библиотек надо класть в каталог
lib вашего репозитория.
-
Нельзя использовать самописные фреймворки и тесты,
запускаемые через
main .
- Сложный вариант
-
Тесты не должны рассчитывать на наличие запущенного
RMI Registry.
-
Создайте класс
BankTests , запускающий тесты.
-
Создайте скрипт, запускающий
BankTests
и возвращающий код (статус) 0
в случае успеха и 1 в случае неудачи.
-
Создайте скрипт, запускающий тесты с использованием
стандартного подхода для вашего тестового фреймворка.
Код возврата должен быть как в предыдущем пункте.
Домашнее задание 11. HelloNonblockingUDP-
Реализуйте клиент и сервер, взаимодействующие по UDP,
используя только неблокирующий ввод-вывод.
-
Класс
HelloUDPNonblockingClient должен
иметь функциональность аналогичную HelloUDPClient ,
но без создания новых потоков.
-
Класс
HelloUDPNonblockingServer должен
иметь функциональность аналогичную HelloUDPServer ,
но все операции с сокетом должны производиться в одном потоке.
-
В реализации не должно быть активных ожиданий,
в том числе через
Selector .
-
Обратите внимание на выделение общего кода старой и новой реализации.
- Бонусный вариант.
Клиент и сервер могут перед началом работы выделить
O(число потоков) памяти.
Выделять дополнительную память во время работы запрещено.
Домашнее задание 12. Статистика текста-
Создайте приложение
TextStatistics ,
анализирующее тексты на различных языках.
-
Аргументы командной строки:
- локаль текста,
- локаль вывода,
- файл с текстом,
- файл отчета.
-
Поддерживаемые локали текста: все локали, имеющиеся в системе.
-
Поддерживаемые локали вывода: русская и английская.
-
Файлы имеют кодировку UTF-8.
-
Подсчет статистики должен вестись по следующим категориям:
- предложения,
- слова,
- числа,
- деньги,
- даты.
-
Для каждой категории должна собираться следующая статистика:
- число вхождений,
- число различных значений,
- минимальное значение,
- максимальное значение,
- минимальная длина,
- максимальная длина,
- среднее значение/длина.
-
Пример отчета:
Анализируемый файл "input.txt"
Сводная статистика
Число предложений: 43.
Число слов: 275.
Число чисел: 40.
Число сумм: 3.
Число дат: 3.
Статистика по предложениям
Число предложений: 43 (43 различных).
Минимальное предложение: "Аргументы командной строки: локаль текста, локаль вывода, файл с текстом, файл отчета.".
Максимальное предложение: "Число чисел: 40.".
Минимальная длина предложения: 13 ("Число дат: 3.").
Максимальная длина предложения: 211 ("GK: если сюда поставить реальное предложение, то процесс не сойдётся").
Средняя длина предложения: 55,465.
Статистика по словам
Число слов: 275 (157 различных).
Минимальное слово: "GK".
Максимальное слово: "языках".
Минимальная длина слова: 1 ("с").
Максимальная длина слова: 14 ("TextStatistics").
Средняя длина слова: 6,72.
Статистика по числам
Число чисел: 40 (24 различных).
Минимальное число: -12345,0.
Максимальное число: 12345,67.
Среднее число: 207,676.
Статистика по суммам денег
Число сумм: 3 (3 различных).
Минимальная сумма: 100,00 ₽.
Максимальная сумма: 345,67 ₽.
Средняя сумма: 222,83 ₽.
Статистика по датам
Число дат: 3 (3 различных).
Минимальная дата: 19 мая 2022 г..
Максимальная дата: 2 июн. 2022 г..
Средняя дата: 26 мая 2022 г..
-
Вы можете рассчитывать на то, что весь текст помещается в память.
-
При выполнении задания следует обратить внимание на:
- Декомпозицию сообщений для локализации.
- Согласование сообщений по роду и числу.
-
Напишите тесты, проверяющие вышеуказанное поведение приложения.
-
Для реализации тестов рекомендуется использовать
JUnit
(Tutorial).
Множество примеров использования можно найти в тестах.
-
Если вы знакомы с другим тестовым фреймворком
(например, TestNG),
то можете использовать его.
-
Нельзя использовать самописные фреймворки и тесты,
запускаемые через
main .
|