Лабораторная работа № V : Коллекции данных и обобщения (Generics)

(проект лабораторной , будет правиться по результатам прием лабы 4)

Лабораторная работа № 5 — «Collections Framework и Generics: репозиторий финансовых операций»

На эту тему РПД выделяет больше всего практического времени среди базовых тем — шесть часов — и это оправданно: здесь впервые соединяются структуры данных, алгоритмическая сложность, equals/hashCode, сортировка и параметризация типов.

Работу целесообразно разделить на две части.

Первая часть — выбор коллекции по семантике.

Приложение должно хранить:


List<Transaction>            — последовательность операций;
Set<Category>                — уникальные категории;
Map<UUID, Transaction>       — поиск транзакции по id;
TreeMap<LocalDate, ...>      — данные в порядке дат.

List моделирует упорядоченную последовательность и допускает повторяющиеся элементы; Map связывает уникальные ключи со значениями. HashSet не гарантирует порядок итерации, зато его базовые операции при нормальном распределении хешей имеют ожидаемую постоянную стоимость; TreeMap, напротив, поддерживает сортировку ключей и гарантирует логарифмическую стоимость containsKey, get, put и remove.

Задания:


найти транзакцию по UUID;
получить все уникальные категории;
сгруппировать суммы по дате без Stream API;
удалить операцию;
отсортировать операции;
определить повторяющиеся категории;

Студент обязан для каждой задачи письменно выбрать структуру и объяснить почему, а не просто выполнить всё через ArrayList.

Эксперимент ArrayList vs LinkedList.

Реализуются четыре сценария:


последовательный проход;
get(i) по случайным индексам;
добавление в конец;
вставка через ListIterator.

Цель не в получении «идеального бенчмарка», а в сопоставлении наблюдений с моделью структуры данных. Отдельно нужно предупредить: один замер System.nanoTime() не превращает лабораторию в профессиональный benchmark; результаты JVM зависят от JIT, прогрева и множества факторов. Итогом является прежде всего анализ сложности, а не соревнование наносекунд.

Вторая часть — Generics.

Студент преобразует конкретное хранилище:


class TransactionRepository { ... }

в обобщённый контракт:


public interface Repository<T, ID> {

    void save(T entity);

    Optional<T> findById(ID id);

    List<T> findAll();

    boolean deleteById(ID id);
}

затем создаёт:


public interface Identifiable<ID> {
    ID getId();
}

и:


public class InMemoryRepository<
        T extends Identifiable<ID>,
        ID
> implements Repository<T, ID> {
    ...
}

Именно здесь хорошо вводить Optional: метод поиска больше не обязан возвращать «магический null».

Потом студент пишет generic-метод копирования/добавления и сталкивается с:


? extends T
? super T

после чего формулирует PECS своими словами.

Отдельный короткий эксперимент на type erasure:


List<String> strings = new ArrayList<>();
List<Integer> integers = new ArrayList<>();

System.out.println(
    strings.getClass() == integers.getClass()
);

и вопросы: почему параметр типа обеспечивает compile-time type safety, но нельзя написать new T() в общем случае; почему raw types вроде List list следует избегать. Спецификация Java описывает реализацию generics через erasure: параметризованный тип во многих runtime-контекстах стирается к соответствующему raw-type представлению.

Сортировка. Transaction получает либо естественный порядок через Comparable<Transaction>, либо студент аргументирует, почему естественного порядка у финансовой операции нет. Не менее трёх альтернативных порядков задаются через Comparator:


по дате;
по сумме;
по категории, затем по дате.

Контрольная задача по эффективности.

Даны 100 000 транзакций. Нужно ответить, какой вариант выбрать для многократного поиска по id:


List<Transaction>

с полным проходом или:


Map<UUID, Transaction>

с индексированием по ключу, а затем провести простой эксперимент.

Автопроверка: CRUD generic repository; невозможность добавить объект неправильного типа; уникальность Set; корректность сортировок; соответствие equals/hashCode; поиск отсутствующего ID возвращает Optional.empty().



Вопросы для углубления: Чем отличаются List, Set, Map и когда применять
каждую структуру?ArrayList vs LinkedList:
отличия по сложности операций и сценарии
выбора. HashMap vs TreeMap, HashSet vs TreeSet:
чем отличаются и что дают сортируемые
структуры?Зачем нужны Comparable и
Comparator?Для чего нужны generics и какие у них
ограничения (type erasure)?
Автор: к.п.н., Румянцев Сергей Александрович, доцент Финансового университета при Правительстве РФ; доцент ОЧУВО Международного инновационного университета; Консалтинг, управление разработкой ПО; системный и бизнес анализ; менеджмент; аналитиз данных; управление ИТ. Телефон для связи +79269444818 (мессенджеры)   Короткая ссылка:
(проект лабораторной , будет правиться по результатам прием лабы 4)

Лабораторная работа № 5 — «Collections Framework и Generics: репозиторий финансовых операций»

На эту тему РПД выделяет больше всего практического времени среди базовых тем — шесть часов — и это оправданно: здесь впервые соединяются структуры данных, алгоритмическая сложность, equals/hashCode, сортировка и параметризация типов.

Работу целесообразно разделить на две части.

Первая часть — выбор коллекции по семантике.

Приложение должно хранить:


List<Transaction>            — последовательность операций;
Set<Category>                — уникальные категории;
Map<UUID, Transaction>       — поиск транзакции по id;
TreeMap<LocalDate, ...>      — данные в порядке дат.

List моделирует упорядоченную последовательность и допускает повторяющиеся элементы; Map связывает уникальные ключи со значениями. HashSet не гарантирует порядок итерации, зато его базовые операции при нормальном распределении хешей имеют ожидаемую постоянную стоимость; TreeMap, напротив, поддерживает сортировку ключей и гарантирует логарифмическую стоимость containsKey, get, put и remove.

Задания:


найти транзакцию по UUID;
получить все уникальные категории;
сгруппировать суммы по дате без Stream API;
удалить операцию;
отсортировать операции;
определить повторяющиеся категории;

Студент обязан для каждой задачи письменно выбрать структуру и объяснить почему, а не просто выполнить всё через ArrayList.

Эксперимент ArrayList vs LinkedList.

Реализуются четыре сценария:


последовательный проход;
get(i) по случайным индексам;
добавление в конец;
вставка через ListIterator.

Цель не в получении «идеального бенчмарка», а в сопоставлении наблюдений с моделью структуры данных. Отдельно нужно предупредить: один замер System.nanoTime() не превращает лабораторию в профессиональный benchmark; результаты JVM зависят от JIT, прогрева и множества факторов. Итогом является прежде всего анализ сложности, а не соревнование наносекунд.

Вторая часть — Generics.

Студент преобразует конкретное хранилище:


class TransactionRepository { ... }

в обобщённый контракт:


public interface Repository<T, ID> {

    void save(T entity);

    Optional<T> findById(ID id);

    List<T> findAll();

    boolean deleteById(ID id);
}

затем создаёт:


public interface Identifiable<ID> {
    ID getId();
}

и:


public class InMemoryRepository<
        T extends Identifiable<ID>,
        ID
> implements Repository<T, ID> {
    ...
}

Именно здесь хорошо вводить Optional: метод поиска больше не обязан возвращать «магический null».

Потом студент пишет generic-метод копирования/добавления и сталкивается с:


? extends T
? super T

после чего формулирует PECS своими словами.

Отдельный короткий эксперимент на type erasure:


List<String> strings = new ArrayList<>();
List<Integer> integers = new ArrayList<>();

System.out.println(
    strings.getClass() == integers.getClass()
);

и вопросы: почему параметр типа обеспечивает compile-time type safety, но нельзя написать new T() в общем случае; почему raw types вроде List list следует избегать. Спецификация Java описывает реализацию generics через erasure: параметризованный тип во многих runtime-контекстах стирается к соответствующему raw-type представлению.

Сортировка. Transaction получает либо естественный порядок через Comparable<Transaction>, либо студент аргументирует, почему естественного порядка у финансовой операции нет. Не менее трёх альтернативных порядков задаются через Comparator:


по дате;
по сумме;
по категории, затем по дате.

Контрольная задача по эффективности.

Даны 100 000 транзакций. Нужно ответить, какой вариант выбрать для многократного поиска по id:


List<Transaction>

с полным проходом или:


Map<UUID, Transaction>

с индексированием по ключу, а затем провести простой эксперимент.

Автопроверка: CRUD generic repository; невозможность добавить объект неправильного типа; уникальность Set; корректность сортировок; соответствие equals/hashCode; поиск отсутствующего ID возвращает Optional.empty().



Вопросы для углубления: Чем отличаются List, Set, Map и когда применять
каждую структуру?ArrayList vs LinkedList:
отличия по сложности операций и сценарии
выбора. HashMap vs TreeMap, HashSet vs TreeSet:
чем отличаются и что дают сортируемые
структуры?Зачем нужны Comparable и
Comparator?Для чего нужны generics и какие у них
ограничения (type erasure)?
https://webprogr.ru/~acO9i
Короткая ссылка на новость:https://webprogr.ru/~acO9i


Последние новости

Лабораторная работа № V : Коллекции данных и обобщения (Generics)

(проект лабораторной , будет правиться по результатам прием лабы 4)

Лабораторная работа № 5 — «Collections Framework и Generics: репозиторий финансовых операций»

На эту тему РПД выделяет больше всего практического времени среди базовых тем — шесть часов — и это оправданно: здесь впервые соединяются структуры данных, алгоритмическая сложность, equals/hashCode, сортировка и параметризация типов.

Работу целесообразно разделить на две части.

Первая часть — выбор коллекции по семантике.

Приложение должно хранить:


List<Transaction>            — последовательность операций;
Set<Category>                — уникальные категории;
Map<UUID, Transaction>       — поиск транзакции по id;
TreeMap<LocalDate, ...>      — данные в порядке дат.

List моделирует упорядоченную последовательность и допускает повторяющиеся элементы; Map связывает уникальные ключи со значениями. HashSet не гарантирует порядок итерации, зато его базовые операции при нормальном распределении хешей имеют ожидаемую постоянную стоимость; TreeMap, напротив, поддерживает сортировку ключей и гарантирует логарифмическую стоимость containsKey, get, put и remove.

Задания:


найти транзакцию по UUID;
получить все уникальные категории;
сгруппировать суммы по дате без Stream API;
удалить операцию;
отсортировать операции;
определить повторяющиеся категории;

Студент обязан для каждой задачи письменно выбрать структуру и объяснить почему, а не просто выполнить всё через ArrayList.

Эксперимент ArrayList vs LinkedList.

Реализуются четыре сценария:


последовательный проход;
get(i) по случайным индексам;
добавление в конец;
вставка через ListIterator.

Цель не в получении «идеального бенчмарка», а в сопоставлении наблюдений с моделью структуры данных. Отдельно нужно предупредить: один замер System.nanoTime() не превращает лабораторию в профессиональный benchmark; результаты JVM зависят от JIT, прогрева и множества факторов. Итогом является прежде всего анализ сложности, а не соревнование наносекунд.

Вторая часть — Generics.

Студент преобразует конкретное хранилище:


class TransactionRepository { ... }

в обобщённый контракт:


public interface Repository<T, ID> {

    void save(T entity);

    Optional<T> findById(ID id);

    List<T> findAll();

    boolean deleteById(ID id);
}

затем создаёт:


public interface Identifiable<ID> {
    ID getId();
}

и:


public class InMemoryRepository<
        T extends Identifiable<ID>,
        ID
> implements Repository<T, ID> {
    ...
}

Именно здесь хорошо вводить Optional: метод поиска больше не обязан возвращать «магический null».

Потом студент пишет generic-метод копирования/добавления и сталкивается с:


? extends T
? super T

после чего формулирует PECS своими словами.

Отдельный короткий эксперимент на type erasure:


List<String> strings = new ArrayList<>();
List<Integer> integers = new ArrayList<>();

System.out.println(
    strings.getClass() == integers.getClass()
);

и вопросы: почему параметр типа обеспечивает compile-time type safety, но нельзя написать new T() в общем случае; почему raw types вроде List list следует избегать. Спецификация Java описывает реализацию generics через erasure: параметризованный тип во многих runtime-контекстах стирается к соответствующему raw-type представлению.

Сортировка. Transaction получает либо естественный порядок через Comparable<Transaction>, либо студент аргументирует, почему естественного порядка у финансовой операции нет. Не менее трёх альтернативных порядков задаются через Comparator:


по дате;
по сумме;
по категории, затем по дате.

Контрольная задача по эффективности.

Даны 100 000 транзакций. Нужно ответить, какой вариант выбрать для многократного поиска по id:


List<Transaction>

с полным проходом или:


Map<UUID, Transaction>

с индексированием по ключу, а затем провести простой эксперимент.

Автопроверка: CRUD generic repository; невозможность добавить объект неправильного типа; уникальность Set; корректность сортировок; соответствие equals/hashCode; поиск отсутствующего ID возвращает Optional.empty().



Вопросы для углубления: Чем отличаются List, Set, Map и когда применять
каждую структуру?ArrayList vs LinkedList:
отличия по сложности операций и сценарии
выбора. HashMap vs TreeMap, HashSet vs TreeSet:
чем отличаются и что дают сортируемые
структуры?Зачем нужны Comparable и
Comparator?Для чего нужны generics и какие у них
ограничения (type erasure)?
Рейтинг@Mail.ru