\documentclass[j-spec.tex]{subfiles}
\usepackage{spreadtab}

\begin{document}
\section{Семинар: Обобщения}
\subsection{Инструментарий}
\begin{itemize}
\item \href{https://docs.google.com/presentation/d/1rWHGQBITRElvyKFEjwe8dOinDbAV2ZW18tAK1FXU48U/edit?usp=share_link}{Презентация} для преподавателя, ведущего семинар;
\item \href{https://drive.google.com/file/d/1LWyE8aEy4-1gsognqhXIXwDcoLviVge4/view}{Фон} GeekBrains для проведения семинара в Zoom;
\item JDK любая 11 версии и выше;
\item \href{https://www.jetbrains.com/idea/download}{IntelliJ IDEA Community Edition} для практики и примеров используется IDEA.
\end{itemize}

\subsection{Цели семинара}
\begin{itemize}
\item Практика создания простых обобщений;
\item Создание собственного обобщённого контейнера с описанием базовых алгоритмов (введение в коллекции);
\item Изучение поведения объекта итератора;
\item Закрепление понимания механизмов работы коллекций.
\end{itemize}

\subsection{План-содержание}
\noindent
\begin{spreadtab}{{longtable}{|p{37mm}|l|l|p{90mm}|}}
\hline
 @ Что происходит         & @ Время     & @ Слайды & @ Описание \\
\hline
\endhead
 @ Организационный момент & 5 tag(beg)  & @ 1-5    & @ Преподаватель ожидает студентов, поддерживает активность и коммуникацию в чате, озвучивает цели и планы на семинар. Важно упомянуть, что выполнение домашних заданий с лекции является, фактически, подготовкой к семинару \\
\hline
 @ Quiz                   & 5           & @ 6-18   & @ Преподаватель задаёт вопросы викторины, через 30 секунд демонстрирует слайд-подсказку и ожидает ответов (по минуте на ответ) \\
\hline
 @ Рассмотрение ДЗ лекции & 10          & @ 19-23  & @ Преподаватель демонстрирует свой вариант решения домашнего задания с лекции, возможно, по предварительному опросу, демонстрирует и разбирает вариант решения одного из студентов \\
\hline
 @ Вопросы и ответы       & 10          & @ 24     & @ Преподаватель ожидает вопросов по теме прошедшей лекции, викторины и продемонстрированной работы \\
\hline
 @ Задание 1              & 10          & @ 25-27  & @ Формирование навыков базовой работы с обобщениями \\
\hline
 @ Задание 2              & 20          & @ 28-30  & @ Практика написания обобщённого кода с дополнительным описанием алгоритмов манипулирования данными \\
\hline
 @ Перерыв (если нужен)   & 5           & @ 31     & @ Преподаватель предлагает студентам перерыв на 5 минут (студенты голосуют) \\ 
\hline
 @ Задание 3              & 20          & @ 32-34  & @ Изучение поведения итератора для понимания механизмов его действия и необходимости его использования в работе \\
\hline
 @ Задание 4              & 20          & @ 35-38  & @ Закрепление понимания механизмов работы коллекций (в том числе с применением итераторов) \\
\hline
 @ Домашнее задание       & 5           & @ 39-40  & @ Объясните домашнее задание, подведите итоги урока \\ 
\hline
 @ Рефлексия              & 10 tag(end) & @ 41-42  & @ Преподаватель запрашивает обратную связь \\ 
\hline
 @ Длительность           & sum(cell(beg):cell(end)) & & \\
\hline
\end{spreadtab}

\subsection{Подробности}
\subsubsection*{Организационный момент}
\begin{itemize}
\item \textbf{Цель этапа:} Позитивно начать урок, создать комфортную среду для обучения.
\item \textbf{Тайминг:} 3-5 минут.
\item \textbf{Действия преподавателя:}
  \begin{itemize}
  \item Запрашивает активность от аудитории в чате;
  \item Презентует цели курса и семинара;
  \item Презентует краткий план семинара и что студент научится делать.
  \end{itemize}
\end{itemize}

\subsubsection*{Quiz}
\begin{itemize}
\item \textbf{Цель этапа:} Вовлечение аудитории в обратную связь.
\item \textbf{Тайминг:} 5--7 минут (4 вопроса, по минуте на ответ).
\item \textbf{Действия преподавателя:}
  \begin{itemize}
  \item Преподаватель задаёт вопросы викторины, представленные на слайдах презентации;
  \item через 30 секунд демонстрирует слайд-подсказку и ожидает ответов.
  \end{itemize}
\item \textbf{Вопросы и ответы:}
  \begin{enumerate}
   \item Какая основная цель использования Java generics? (1)
    \begin{enumerate}
    \item Упрощение программирования и повышение безопасности типов
    \item Ускорение работы программы и сокращение объема кода
    \item Позволяют работать с различными базами данных одновременно
    \end{enumerate}
%   Неверные ответы: b) и c) - generics не связаны с ускорением работы программы или работой с базами данных, их основная цель - добавить типовую безопасность и упростить программирование.
   \item Что такое параметризованный класс в Java generics? (1)
    \begin{enumerate}
    \item Класс, который принимает параметр типа
    \item Класс, который имеет только один параметр типа
    \item Класс, который можно использовать только с определенным типом данных
    \end{enumerate}
%   Неверные ответы: b) и c) - параметризованный класс может иметь любое количество параметров типа и может быть использован с различными типами данных.
   \item Какие ограничения можно использовать с wildcard в Java generics? (1)
    \begin{enumerate}
    \item extends и super
    \item only
    \item extends
    \end{enumerate}
%   Неверные ответы: b) и c) - в generics для ограничения типа используются ключевые слова extends и super, а не only или extends.

   \item Можно ли создать экземпляр обобщенного типа в Java, внутри класса, описывающего этот тип? (2)
    \begin{enumerate}
    \item Да, это возможно
    \item Нет, такое создание экземпляров обобщенных типов запрещено
    \item Это зависит от контекста использования обобщенного типа
    \end{enumerate}
%   Неверные ответы: a) и c) - экземпляры обобщенных типов не могут быть созданы в Java из-за стирания типов, однако можно создать экземпляр обобщенного класса, указав конкретный тип данных.
  \end{enumerate}
\end{itemize}

\subsubsection*{Рассмотрение ДЗ}
\begin{itemize}
\item \textbf{Цель этапа:} Пояснить не очевидные моменты в формулировке ДЗ с лекции, синхронизировать прочитанный на лекции материал к началу семинара.
\item \textbf{Тайминг:} 15-20 минут.
\item \textbf{Действия преподавателя:}
  \begin{itemize}
  \item Преподаватель демонстрирует свой вариант решения домашнего задания из лекции;
  \item возможно, по предварительному опросу, демонстрирует и разбирает вариант решения одного из студентов.
  \end{itemize}
\item \textbf{Домашнее задание из лекции:}
  \begin{itemize}
  \item Написать метод, который меняет два элемента массива местами (массив может быть любого ссылочного типа);

    \textbf{Вариант решения}

    Задание с подвохом, при решении необязательно было использовать дженерики, формулировка задания не ограничивает используемые в массиве типы, наоборот, явно проговаривается, что массив может быть любого типа.
    \begin{lstlisting}[language=Java,style=JCodeStyle]
private static void swap(Object[] arr, int from, int to) {
    Object temp = arr[from];
    arr[from] = arr[to];
    arr[to] = temp;
}

public static void main(String[] args) {
    Object[] arr = {1, 2.0f, "hello"};
    System.out.println(Arrays.toString(arr));
    swap(arr, 0, 2);
    System.out.println(Arrays.toString(arr));
}
\end{lstlisting}
    
\item Большая задача:
  \begin{itemize}
  \item Есть классы \code{Fruit} -> \code{Apple}, \code{Orange}; (больше не надо);
  \item Класс \code{Box} в который можно складывать фрукты, коробки условно сортируются по типу фрукта, поэтому в одну коробку нельзя сложить и яблоки, и апельсины; Для хранения фруктов внутри коробки можете использовать \code{ArrayList};
  \item Сделать метод \code{getWeight()} который высчитывает вес коробки, зная количество фруктов и вес одного фрукта(вес яблока -- \code{1.0f}, апельсина -- \code{1.5f}, не важно в каких единицах);
  \item Внутри класса коробки сделать метод \code{compare()}, который позволяет сравнить текущую коробку с той, которую подадут в \code{compare()} в качестве параметра, \code{true} -- если их веса равны, \code{false} в противном случае (коробки с яблоками возможно сравнивать с коробками с апельсинами);
  \item Написать метод, который позволяет пересыпать фрукты из текущей коробки в другую коробку (при этом, нельзя яблоки высыпать в коробку с апельсинами), соответственно, в текущей коробке фруктов не остается, а в другую перекидываются объекты, которые были в этой коробке.
  \end{itemize}

    \textbf{Вариант решения}
Создали фрукты с каким то разным весом, создали коробку, которая может вместить только фрукты. Надо фрукты там как то хранить, поэтому -- список. Соответственно при создании можем в нашу коробку какие то фрукты накидать. Соответственно метод, который будет уметь добавлять фрукты в коробку
    \begin{lstlisting}[language=Java,style=JCodeStyle,caption={ }]
private interface Fruit { float getWeight(); }
private static class Apple implements Fruit {
    static final float weight = 1.0f;
    @Override public float getWeight() { return weight; }
}
private static class Orange implements Fruit {
    static final float weight = 1.5f;
    @Override public float getWeight() { return weight; }
}
public static class Box<T extends Fruit> {
    private final List<T> container;
    Box(T[] init) {
        container = new ArrayList<>();
        for (T f : init) { add(f); }
    }
    void add(T fruit) { container.add(fruit); }
    void print() { System.out.println(getWeight()); }
}
\end{lstlisting}

Поскольку в коробке у нас могут быть только одно типа фрукты -- мы можем не перебирать каждый из них, а умножить вес одного на количество.
    \begin{lstlisting}[language=Java,style=JCodeStyle,caption={ }]
float getWeight() {
    return (container.isEmpty())
            ? 0
            : container.get(0).getWeight() * container.size();
}
\end{lstlisting}

Можно было, по большому счёту, переопределить метод equals() или написать свой метод compare() который принимает вторую коробку и сравнивает вес. Сравнивать можно любые фрукты, значит в методе не подходит параметр типа \code{<T>}
    \begin{lstlisting}[language=Java,style=JCodeStyle,caption={ }]
boolean compare(Box<?> with) {
    return this.getWeight() - with.getWeight() < 0.0001;
}
    \end{lstlisting}

Осталось только уметь пересыпать из одной коробки в другую не смешивая. На входе должна быть коробка того же типа, что и у объекта, и тут два пути, либо пересыпать всё из текущей коробки в другую, либо из другой в текущую, метод назван \code{transferTo()}, поэтому пересыпаться фрукты будут из текущей коробки. Возникает вопрос: если создаётся коробка с яблоками \code{Box<Apple>} и коробка с фруктами \code{Box<Fruit>}, должна ли быть возможность перекинуть из яблочной во фруктовую? Однозначно, нет. Поэтому, в аргументе метода используется \code{Box<? super T>}, таким образом яблоки возможно кидать в яблоки или в яблочных родителей, но не в апельсины.
    \begin{lstlisting}[language=Java,style=JCodeStyle,caption={ }]
void transferTo(Box<? super T> dest) {
    dest.container.addAll(container);
    container.clear();
}
    \end{lstlisting}

  \end{itemize}
\end{itemize}

\subsubsection*{Вопросы и ответы}
\begin{itemize}
\item \textbf{Ценность этапа} Вовлечение аудитории в обратную связь, пояснение неочевидных моментов в материале лекции и другой проделанной работе. 
\item \textbf{Тайминг} 5-15 минут
\item \textbf{Действия преподавателя}
  \begin{itemize}
  \item Преподаватель ожидает вопросов по теме прошедшей лекции, викторины и продемонстрированной работы;
  \item Если преподаватель затрудняется с ответом, необходимо мягко предложить студенту ответить на его вопрос на следующем семинаре (и не забыть найти ответ на вопрос студента!);
  \item Предложить и показать пути самостоятельного поиска студентом ответа на заданный вопрос;
  \item Посоветовать литературу на тему заданного вопроса;
  \item Дополнительно указать на то, что все сведения для выполнения домашнего задания, прохождения викторины и работы на семинаре были рассмотрены в методическом материале к этому или предыдущим урокам.
  \end{itemize}
\end{itemize}

\subsubsection*{Задание 1}
\begin{itemize}
\item \textbf{Ценность этапа} Формирование навыков базовой работы с обобщениями.
\item \textbf{Тайминг} 10-15 мин
\item \textbf{Действия преподавателя}
  \begin{itemize}
  \item Выдать задание студентам;
  \item Подробно объяснить, что именно требуется от студентов, избегая упоминания конкретных языковых конструкций;
  \item Пояснить студентам пользу и необходимость следования паттерну MVC, проговорить важность разделения логики и открывающиеся возможности при правильном проектировании.
  \end{itemize}
\item \textbf{Задание}:
  \begin{itemize}
  \item Создать обобщенный класс с тремя параметрами (\code{T}, \code{V}, \code{K}). Класс содержит три переменные типа (\code{T}, \code{V}, \code{K}), конструктор, принимающий на вход параметры типа (\code{T}, \code{V}, \code{K}), методы возвращающие значения трех переменных. Создать метод, выводящий на консоль имена классов для трех переменных класса. Наложить ограничения на параметры типа: \code{T} должен реализовать интерфейс \code{Comparable} (классы оболочки, \code{String}), \code{V} должен реализовать интерфейс \code{DataInput} и расширять класс \code{InputStream}, \code{K} должен расширять класс \code{Number}.

    \textbf{Вариант решения}

    \begin{lstlisting}[language=Java,style=JCodeStyle]
    private static class MyClass<T extends Comparable, V extends InputStream & Serializable, K extends Number> {
        T t; V v; K k;

        MyClass(T t, V v, K k) {
            this.t = t; this.v = v; this.k = k;
        }

        public T getT() { return t; }
        public V getV() { return v; }
        public K getK() { return k; }

        void print() {
            System.out.printf("t = %s, v = %s, k = %s",
                    t.getClass().getName(),
                    v.getClass().getName(),
                    k.getClass().getName());
        }
    }
    \end{lstlisting}

  \end{itemize}
\end{itemize}

\subsubsection*{Задание 2}
\begin{itemize}
\item \textbf{Ценность этапа} Практика написания обобщённого кода с дополнительным описанием алгоритмов манипулирования данными.
\item \textbf{Тайминг} 15-20 мин
\item \textbf{Действия преподавателя}
  \begin{itemize}
  \item Выдать задание студентам;
  \item Подробно объяснить, что именно требуется от студентов, избегая упоминания конкретных языковых конструкций;
  \item Если группа студентов справилась с заданием, а времени осталось более 5 минут, выдавать группе задания «со звёздочкой».
  \end{itemize}
\item \textbf{Задание}:
  \begin{itemize}
  \item Описать собственную коллекцию -- список на основе массива. Коллекция должна иметь возможность хранить любые типы данных, иметь методы добавления и удаления элементов.
    
  \textbf{Вариант решения}

\begin{lstlisting}[language=Java,style=JCodeStyle]
private static class OwnList<T> {
    Object[] arr;
    int count;

    OwnList() {
        arr = new Object[1];
        count = 0;
    }

    void add(T item) {
        if (count == arr.length) {
            Object[] newArr = new Object[arr.length * 2];
            System.arraycopy(arr, 0, newArr, 0, arr.length);
            arr = newArr;
        }
        arr[count++] = item;
    }

    T remove() {
        if (count == 0) throw new NoSuchElementException();
        T temp = (T) arr[--count];
        arr[count] = null;
        return temp;
    }

    @Override
    public String toString() {
        return Arrays.toString(arr);
    }
}
\end{lstlisting}
  
  \end{itemize}
\end{itemize}

\subsubsection*{Задание 3}
\begin{itemize}
\item \textbf{Ценность этапа} Изучение поведения итератора для понимания механизмов его действия и необходимости его использования в работе.
\item \textbf{Тайминг} 20-25 мин
\item \textbf{Действия преподавателя}
  \begin{itemize}
  \item Выдать задание студентам;
  \item Подробно объяснить, что именно требуется от студентов, избегая упоминания конкретных языковых конструкций;
  \end{itemize}
\item \textbf{Задание}: 
  \begin{itemize}
  \item Написать итератор по массиву. Итератор -- это объект, осуществляющий движение по коллекциям любого типа, содержащим любые типы данных. Итераторы обычно имеют только два метода -- проверка на наличие следующего элемента и переход к следующему элементу. Но также, особенно в других языках программирования, возможно встретить итераторы, реализующие дополнительную логику.
  
  \textbf{Вариант решения}

  \begin{lstlisting}[language=Java,style=JCodeStyle]
    private static class ArrayIterator<T> {

        private final T[] array;
        private int index = 0;

        public ArrayIterator(T[] array) {
            this.array = array;
        }

        public boolean hasNext() {
            return index < array.length;
        }

        public T next() {
            if(!hasNext())
                throw new NoSuchElementException();
            return array[index++];
        }
    }

    public static void main(String[] args) {
        Integer[] arr = {1,2,3,4};
        ArrayIterator<Integer> it = new ArrayIterator<>(arr);
        while (it.hasNext()) {
            System.out.print(it.next() + " ");
        }
    }
  \end{lstlisting}
  \item [$*_1$] Написать итератор таким образом, чтобы его возможно было использовать для цикла \code{foreach}.
  
    \textbf{Вариант решения}

    Указать, что для этого достаточно реализовать интерфейс \code{Iterator<T>}.

  \begin{lstlisting}[language=Java,style=JCodeStyle]
class ArrayIterator<T> implements Iterator<T>{

    private T[] array;
    private int index = 0;

    public ArrayIterator(T[] array) {
        this.array = array;
    }

    @Override
    public boolean hasNext() {
        return index < array.length;
    }

    @Override
    public T next() {
        if(!hasNext())
            throw new NoSuchElementException();
        return array[index++];
    }
}
  \end{lstlisting}

\end{itemize}
\end{itemize}

\subsubsection*{Задание 4}
\begin{itemize}
\item \textbf{Ценность этапа} Закрепление понимания механизмов работы коллекций (в том числе с применением итераторов).
\item \textbf{Тайминг} 20-25 мин
\item \textbf{Действия преподавателя}
  \begin{itemize}
  \item Выдать задание студентам;
  \item Подробно объяснить, что именно требуется от студентов, избегая упоминания конкретных языковых конструкций;
  \end{itemize}
\item \textbf{Задание}:
  \begin{itemize}
  \item Описать интерфейс \code{Person} с методами \code{doWork()} и \code{haveRest()}. Написать два класса работник и бездельник, реализующих интерфейс. Работник работает, и не умеет бездельничать, в то время как бездельник не умеет работать, но умеет отдыхать. Написать обобщённые классы \code{Workplace} и \code{Club}, содержащие массив из \code{Person}. В классах необходимо вызывать у всего массива людей вызывать соответствующие методы.
  
  \textbf{Вариант решения}

  \begin{lstlisting}[language=Java,style=JCodeStyle]
    interface Person {
        void doWork();
        void haveRest();
    }

    private static class Worker implements Person {
        @Override public void doWork() {
            System.out.println("Work!"); }
        @Override public void haveRest() {
            System.out.println("What?");
        }
    }

    private static class Idler implements Person {
        @Override public void doWork() {
            System.out.println("No!"); }
        @Override public void haveRest() {
            System.out.println("Chill!");
        }
    }

    private static class Workplace<T extends Person> {
        Person[] arr;
        public Workplace(T... people) {
            arr = people;
        }
        void work() {
            for (Person person : arr) { person.doWork(); }
        }
    }
    private static class Club<T extends Person> {
        Person[] arr;
        public Club(T... people) {
            arr = people;
        }
        void chill() {
            for (Person person : arr) { person.haveRest(); }
        }
    }

    public static void main(String[] args) {
        Workplace<Person> w = new Workplace<>(new Worker(), new Worker(), new Idler());
        Club<Person> c = new Club<>(new Worker(), new Worker(), new Idler());
        w.work();
        c.chill();
    }
  \end{lstlisting}

\end{itemize}
\end{itemize}

\subsubsection*{Домашнее задание}
\begin{itemize}
\item \textbf{Ценность этапа} Задать задание для самостоятельного выполнения между занятиями.
\item \textbf{Тайминг} 5-10 минут.
\item \textbf{Действия преподавателя}
  \begin{itemize}
  \item Пояснить студентам в каком виде выполнять и сдавать задания
  \item Уточнить кто будет проверять работы (преподаватель или ревьювер)
  \item Объяснить к кому обращаться за помощью и где искать подсказки
  \item Объяснить где взять проект заготовки для дз
  \end{itemize}
\item \textbf{Задания}
  \begin{enumerate}
  \item [5-25 мин] Выполнить все задания семинара, если они не были решены, без ограничений по времени;

    \textbf{Все варианты решения приведены в тексте семинара выше}
  \item [25 мин] 1. Внедрить итератор из задания 2 в коллекцию, написанную в задании 3 таким образом, чтобы итератор был внутренним классом и, соответственно, объектом в коллекции.
  
    \begin{lstlisting}[language=Java,style=JCodeStyle]
private static class OList<T> implements Iterable<T> {
    class ArrayIterator<T> implements Iterator<T> {
        private int index = 0;

        @Override
        public boolean hasNext() {
            return index < count;
        }

        @Override
        public T next() {
            if(!hasNext())
                throw new NoSuchElementException();
            return (T) arr[index++];
        }
    }

    Object[] arr;
    int count;
    Main.OList.ArrayIterator iter;

    OList() {
        arr = new Object[1];
        count = 0;
        this.iter = new ArrayIterator<T>();
    }

    void add(T item) {
        if (count == arr.length) {
            Object[] newArr = new Object[arr.length * 2];
            System.arraycopy(arr, 0, newArr, 0, arr.length);
            arr = newArr;
        }
        arr[count++] = item;
    }
    T remove() {
        if (count == 0) throw new NoSuchElementException();
        --count;
        T temp = (T) arr[count];
        arr[count] = null;
        return temp;
    }

    @Override
    public Iterator<T> iterator() {
        return iter;
    }

    @Override
    public Spliterator<T> spliterator() {
        return Iterable.super.spliterator();
    }

    @Override
    public String toString() {
        return Arrays.toString(arr);
    }
}
    \end{lstlisting}

  \item [15 мин] 2. Написать класс Калькулятор (необобщенный), который содержит обобщенные статические методы: \code{sum()}, \code{multiply()}, \code{divide()}, \code{subtract()}. Параметры этих методов -- два \textbf{числа} разного типа, над которыми должна быть произведена операция.
    \begin{lstlisting}[language=Java,style=JCodeStyle]
private static class Calculator {
    public static <T extends Number, U extends Number> double sum(T num1, U num2) {
        return num1.doubleValue() + num2.doubleValue();
    }

    public static <T extends Number, U extends Number> double multiply(T num1, U num2) {
        return num1.doubleValue() * num2.doubleValue();
    }

    public static <T extends Number, U extends Number> double divide(T num1, U num2) {
        return num1.doubleValue() / num2.doubleValue();
    }

    public static <T extends Number, U extends Number> double subtract(T num1, U num2) {
        return num1.doubleValue() - num2.doubleValue();
    }
}

public static void main(String[] args) {
    System.out.println(Calculator.sum(2, 2.0));
    System.out.println(Calculator.multiply(2.0f, 2.0));
    System.out.println(Calculator.divide(2L, 2.0));
    System.out.println(Calculator.subtract(2, 2));
}
    \end{lstlisting}
  \item [10 мин] 3. Напишите обобщенный метод \code{compareArrays()}, который принимает два массива и возвращает \code{true}, если они одинаковые, и \code{false} в противном случае. Массивы могут быть любого типа данных, но должны иметь одинаковую длину и содержать элементы одного типа.

    \begin{lstlisting}[language=Java,style=JCodeStyle]
private static <T> boolean compareArrays(T[] array1, T[] array2) {
    if (array1.length != array2.length) {
        return false;
    }
    
    for (int i = 0; i < array1.length; i++) {
        if (!array1[i].equals(array2[i])) {
            return false;
        }
    }
    
    return true;
}
    \end{lstlisting}
  \item [10 мин] 4. Напишите обобщенный класс \code{Pair}, который представляет собой пару значений разного типа. Класс должен иметь методы \code{getFirst()}, \code{getSecond()} для получения значений пары, а также переопределение метода \code{toString()}, возвращающее строковое представление пары.        
    \begin{lstlisting}[language=Java,style=JCodeStyle]
private static class Pair<T1, T2> {
    private T1 first;
    private T2 second;
    
    public Pair(T1 first, T2 second) {
        this.first = first;
        this.second = second;
    }
    
    public T1 getFirst() { return first; }
    public T2 getSecond() { return second; }
    
    @Override public String toString() {
        return "(" + first + ", " + second + ")";
    }
}
    
public static void main(String[] args) {
    Pair<Integer, String> pair1 = new Pair<>(1, "one");
    System.out.println(pair1.getFirst()); // 1
    System.out.println(pair1.getSecond()); // "one"
    System.out.println(pair1); // "(1, one)"
    
    Pair<String, Double> pair2 = new Pair<>("pi", 3.14);
    System.out.println(pair2.getFirst()); // "pi"
    System.out.println(pair2.getSecond()); // 3.14
    System.out.println(pair2); // "(pi, 3.14)"
}
    \end{lstlisting}
  \end{enumerate}
\end{itemize}

\subsubsection*{Рефлексия и завершение семинара}
\begin{itemize}
\item \textbf{Цель этапа:} Привести урок к логическому завершению, посмотреть что студентам удалось, что было сложно и над чем нужно еще поработать
\item \textbf{Тайминг:} 5-10 минут
\item \textbf{Действия преподавателя:}
  \begin{itemize}
  \item Запросить обратную связь от студентов.
  \item Подчеркните то, чему студенты научились на занятии.
  \item Дайте рекомендации по решению заданий, если в этом есть необходимость
  \item Дайте краткую обратную связь студентам.
  \item Поделитесь ощущением от семинара.
  \item Поблагодарите за проделанную работу.
  \end{itemize}
\end{itemize}

\newpage
\end{document}
