Похожие презентации:
StreamApi + ReflectionApi + Collections Pres
1.
COLLECTIONS +STREAM API +
REFLECTION API
{}
begin
2.
ЦЕЛИ ЗАНЯТИЯ1. Закрепить умение выбирать
оптимальные структуры
данных под конкретные задачи.
2. Научиться писать более
"элегантный" код
с использованием современных
средств java (дженерики, stream
api, лямбды, reflection api).
ref
@
3.
РЕЗУЛЬТАТОМ ЗАНЯТИЯ СТАНЕТ//
Будете знать:
1. 7 основных коллекций
и отличия в их реализации.
2. Зачем настраивать параметры
коллекций и как использовать
свои объекты в коллекциях.
/>
3. Самые распространенные ошибки
при использовании
дженериков на примерах.
4. Зачем используется stream api и лямбды
и как выполняется написанный с их помощью код
(порядок выполнения, потоки и т.п.).
&
%
ref
5. Где и как использовать в коде
reflection api.
@
4.
РЕЗУЛЬТАТОМ ЗАНЯТИЯ СТАНЕТ//
Научитесь:
1. Выбрать оптимальную
структуру данных
в зависимости от задачи
и обосновать свой выбор
/>
2. Писать сложные
обработчики коллекций
с использованием
Stream API и лямбд.
3. Работать с полями классов
к которым нет доступа
напрямую.
&
%
ref
@
5.
ТЕМЫКоллекции
разница в реализации
и скорости выполнения
операций
Stream API
работаем с коллекциями,
используем лямбды
для обработки
Дженерики
как можно использовать
для написания более
универсального кода
для работы с коллекциями.
Распространенные ошибки.
Reflection API
варианты применения
на реальных примерах
ref
@
6.
ПРАВИЛА ВЗАИМОДЕЙСТВИЯБудьте с нами!
Отложите телефон,
рабочие дела,
мессенджеры.
Выключайте микрофон,
когда говорит ведущий.
Задавайте вопросы.
Это поможет
разобраться в теме.
Выполняйте практику
вместе с экспертом
во время занятия.
Будьте активны!
Участвуйте в интерактивах.
ref
@
7.
ГДЕ ВОЗНИКЛИСАМЫЕ БОЛЬШИЕ
ТРУДНОСТИ?
Напишите в чате тему / подтему,
где у вас возникли проблемы
при самостоятельном разборе материала
Форматы
выполнения:
индивидуально
Чат
5 минут
8.
Тема 1КОЛЛЕКЦИИ
{}
begin
9.
ПЛАН• Основные коллекции
• Разница в их реализации
• Скорость работы основных операций
• Параметры конфигурации коллекций
ref
@
5
10.
ИЕРАРХИЯ КОЛЛЕКЦИЙref
@
11.
КОЛЛЕКЦИЯ №1: ARRAY LISTВремя выполнения
основных операций:
• получение элемента
по индексу = О(1)
• добавление элемента
в конец = O(1),
но в худшем случае за O(N)
• добавление элемента
в случайное место = O(N)
• проверка наличия
элемента = O(N)
ref
• удаление элемента = O(N)
@
12.
КОЛЛЕКЦИЯ №2: LINKED LISTВремя выполнения:
• получение элемента
по индексу = O(N)
• добавление элемента
в конец = O(1)
• добавление элемента
в случайное место = O(N)
• проверка наличия элемента =
O(N)
ref
• удаление элемента = O(N)
@
13.
КОЛЛЕКЦИЯ №3: QUEUEОсновные операции:
• получение головного элемента
(без удаления)
• получение головного элемента
(с удалением)
• добавление элемента в конец
очереди
ref
@
14.
КОЛЛЕКЦИЯ №4: HASHMAPВремя выполнения
основных операций:
• получение элемента
по индексу = O(1),
в худшем случае O(log N)
• добавление элемента
в случайное место = O(1),
в худшем случае O(log N)
• проверка наличия элемента =
O(1), в худшем случае O(log N)
• удаление элемента = O(1),
в худшем случае O(log N)
@
ref
15.
КОЛЛЕКЦИЯ №5: TREEMAPВремя выполнения
основных операций:
• получение элемента
по индексу = O(log N)
• добавление элемента
в случайное место = O(log N)
• проверка наличия
элемента = O(log N)
• удаление элемента = O(log N)
ref
@
16.
КОЛЛЕКЦИЯ №6: HASHSETВремя выполнения
основных операций:
• получение элемента по индексу = O(1),
в худшем случае O(log N)
• добавление элемента
в случайное место = O(1),
в худшем случае O(log N)
• проверка наличия элемента = O(1),
в худшем случае O(log N)
• удаление элемента = O(1),
в худшем случае O(log N)
@
ref
17.
КОЛЛЕКЦИЯ №7: TREESETВремя выполнения
основных операций:
• получение элемента
по индексу = O(log N)
• добавление элемента
в случайное место = O(log N)
• проверка наличия
элемента = O(log N)
• удаление элемента = O(log N)
ref
@
18.
ПРАКТИКА!Выбираем наиболее подходящую для задачи коллекцию
ref
@
19.
КАК БУДЕМВЫБИРАТЬ
1
6 задач
2
Пишем в чат самый подходящий
из изученных ранее вариантов коллекций
3
Обсуждаем результаты
Форматы
выполнения:
индивидуально
Чат
10 минут
20.
ЗАДАЧА №1Есть список организаторов разных потоков курса. Списки в
рамках потока не меняются, могут только добавляться новые
потоки со своими организаторами.
Самые частые операции:
• получение списка организаторов
по конкретному потоку
• получение информации об одном
из организаторов потока
• добавление списка организаторов нового потока
21.
ЗАДАЧА №1Есть список организаторов разных потоков курса. Списки в
рамках потока не меняются, могут только добавляться новые
потоки со своими организаторами.
Самые частые операции:
• получение списка организаторов
по конкретному потоку
• получение информации об одном
из организаторов потока
• добавление списка организаторов нового потока
HASHMAP
22.
ЗАДАЧА №2Есть список студентов текущего курса, который пополняется
новыми участниками по мере набора. Участники могут также
удаляться, если они были отчислены из-за неуспеваемости.
Основные операции:
• добавление нового студента
• удаление студента
• получение списка студентов
23.
ЗАДАЧА №2Есть список студентов текущего курса, который пополняется
новыми участниками по мере набора. Участники могут также
удаляться, если они были отчислены из-за неуспеваемости.
Основные операции:
• добавление нового студента
• удаление студента
• получение списка студентов
ARRAYLIS
T
24.
ЗАДАЧА №3Есть список кандидатов для прохождения курса.
Приемная комиссия должна обработать их анкеты в том
порядке, в котором они были поданы.
Основные операции:
• добавление новых кандидатов
• получение анкеты кандидата в порядке очередности
(кто раньше пришел, у того больше шансов
для попадания на курс) и удаление анкеты после обработки
25.
ЗАДАЧА №3Есть список кандидатов для прохождения курса.
Приемная комиссия должна обработать их анкеты в том
порядке, в котором они были поданы.
Основные операции:
• добавление новых кандидатов
• получение анкеты кандидата в порядке очередности
(кто раньше пришел, у того больше шансов
для попадания на курс) и удаление анкеты после обработки
QUEUE
26.
ЗАДАЧА №4Есть общая база преподавателей всех потоков курса.
При добавлении новых преподавателей, важно сохранять
алфавитный порядок, порядок их добавления не важен.
Основные операции:
• получение списка преподавателей
• добавление нового преподавателя с поддержкой алфавитного
порядка
• получение первого/последнего преподавателя в списке
27.
ЗАДАЧА №4Есть общая база преподавателей всех потоков курса.
При добавлении новых преподавателей, важно сохранять
алфавитный порядок, порядок их добавления не важен.
Основные операции:
• получение списка преподавателей
• добавление нового преподавателя с поддержкой алфавитного
порядка
• получение первого/последнего преподавателя в списке
TREESET
28.
ЗАДАЧА №5Есть список задач для проверочных работ.
Список постоянно пополняется новыми задачами,
удаляются устаревшие. Со списком активно работают
при составлении теста — проходят по списку,
возвращаются к заинтересовавшим задачам.
Основные операции:
• проход по списку в двух направлениях
• добавление элемента в конец
• удаление элемента
29.
ЗАДАЧА №5Есть список задач для проверочных работ.
Список постоянно пополняется новыми задачами,
удаляются устаревшие. Со списком активно работают
при составлении теста — проходят по списку,
возвращаются к заинтересовавшим задачам.
Основные операции:
• проход по списку в двух направлениях
• добавление элемента в конец
• удаление элемента
LINKEDLIST
30.
ЗАДАЧА №6Есть список выпускников курса. В него добавляются новые
люди после выпуска. Важно, что список уникальный —
если человек закончил несколько потоков, он должен
присутствовать в списке один раз.
Основные операции:
• добавление в список
• получение списка
31.
ЗАДАЧА №6Есть список выпускников курса. В него добавляются новые
люди после выпуска. Важно, что список уникальный —
если человек закончил несколько потоков, он должен
присутствовать в списке один раз.
Основные операции:
• добавление в список
• получение списка
HASHSET
32.
Тема 2ДЖЕНЕРИКИ
И ОШИБКИ ИХ
ИСПОЛЬЗОВАНИЯ
{}
begin
33.
СОДЕРЖАНИЕ• Примеры использования
• Самые распространенные ошибки
• Как избежать их в будущем
ref
@
5
34.
ЗАЧЕМ НУЖНЫ?//
Явное указание ожидаемых типов
в коллекциях и объектах
Избежание ошибок
в коде на этапе компиляции
Сокращение кода за счет отсутствия необходимости
явного приведения и проверки типов
Задание единичных и множественных
ограничений на типы принимаемых объектов
/>
&
%
ref
Уменьшение дублирования кода за счет реализации
общих типизированных методов и классов
@
35.
ГДЕ ПРИМЕНЯЕМ?//
Во всех коллекциях и объектах,
где работаем с заранее
определенными типами данных
/>
В методах и классах, которые работают
только с заданными видами объектов
(например, наследниками одного из
классов)
В местах дублирования методов
и классов, где для параметров разных
типов сохраняется одинаковое поведение
&
%
ref
@
36.
ПРИМЕР ОШИБКИ №1Хотим выполнить присвоение массивов чисел (String в raw type)
public static void genericsWithNoType() {
List<String> stringsList = new ArrayList<>(asList("s1", "s2"));
// ...
// ...
List preparedDataList = new ArrayList<Long>(asList(1L, 2L, 3L));
preparedDataList = stringsList;
preparedDataList.add(4L);
// ...
// ...
Long lastAddedNumber = preparedDataList.get(2);
}
ref
@
37.
КАК ПРАВИЛЬНОВ IDE будет отображаться, что такое присваивание невалидно
public static void genericsWithNoType() {
List<String> stringsList = new ArrayList<>(asList("s1", "s2"));
// ...
// ...
List<Long> preparedDataList = new ArrayList<Long>(asList(1L, 2L,
3L));
preparedDataList = stringsList;
preparedDataList.add(4L);
// ...
// ...
Long lastAddedNumber = preparedDataList.get(2);
}
ref
@
38.
ПРИМЕР ОШИБКИ №2Хотим выполнить присвоение массивов чисел (Long в Number)
public final class Long extends Number implements
Comparable<Long>
public static void genericsWithHierarchy() {
List<Long> longList = asList(1L, 2L, 3L);
List<Number> numbersList = asList(1, 2, 3);
numbersList = longList;
}
ref
@
39.
КАК ПРАВИЛЬНОИз иерархии типов не следует такая же иерархия коллекций элементов этого типа
public static void genericsWithHierarchy() {
List<? extends Long> longList = asList(1L, 2L, 3L);
List<? extends Number> numbersList = asList(1, 2, 3);
numbersList = longList;
}
ref
@
40.
ПРИМЕР ОШИБКИ №3Метод добавления нового элемента в список чисел
public static void genericsWithIncreasingList() {
List<Integer> numbers = new ArrayList<>(asList(1, 2));
addNewElement(numbers, 3);
}
public static void addNewElement(List<? extends Number> list,
Integer elementValue) {
list.add(elementValue);
}
@
ref
41.
КАК ПРАВИЛЬНОПринцип PECS (producer extends, consumer super)
public static void genericsWithIncreasingList() {
List<Integer> numbers = new ArrayList<>(asList(1, 2));
addNewElement(numbers, 3);
}
public static void addNewElement(List<? super Integer> list,
Integer elementValue) {
list.add(elementValue);
}
ref
@
42.
ПРИМЕР ОШИБКИ №4Метод с различным поведением в зависимости от типа входных данных
public <T> int resolveStatusCode(T parameter) {
if (parameter instanceof String) {
return 1;
} else if (parameter instanceof Long) {
return 2;
} else {
//
}
return 0;
}
ref
@
43.
КАК ПРАВИЛЬНОНе пытаемся использовать дженерики там, где проще обойтись без них
public int resolveStatusCode(String parameter) {
return 1;
}
public int resolveStatusCode(Long parameter) {
return 2;
}
ref
@
44.
ГДЕ ЕЩЕ МОГУТ БЫТЬ ПРОБЛЕМЫ?//
Нельзя использовать примитивные типы
Нельзя явно создать экземпляр параметризированного типа
Нельзя создать массив параметризованных типов
Нельзя ловить и бросать исключения параметризованных
типов
Нельзя объявить статическое поле параметризованного типа
/>
&
%
ref
@
45.
Тема 3STREAM API
И ЛЯМБДЫ
{}
begin
46.
ПЛАН• Зачем использовать
• Как реализованы
• Порядок применения операторов
• Многопоточность
ref
@
5
47.
ЛЯМБДЫ//
Лямбда — функция с параметрами (блок кода),
которую можно передавать в другие методы
в качестве аргумента.
В отличие от других методов, не имеет имени.
/>
По сути является реализацией
функционального интерфейса.
Общий синтаксис: (параметры) -> {тело метода}
Используются для повышения
читаемости и упрощения кода.
&
%
ref
@
48.
ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ@Test
public void sortingWithComparator() {
List<Integer> numbersList = asList(1, 2, 3, 4);
Comparator<Integer> reversedOrder = new Comparator<Integer>() {
@Override
public int compare(Integer n1, Integer n2) {
return n2 - n1;
}
};
numbersList.sort(reversedOrder);
}
@Test
public void sortingWithLambda() {
List<Integer> numbersList = asList(1, 2, 3, 4);
ref
numbersList.sort((n1, n2) -> n2 - n1);
}
@
49.
ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ@FunctionalInterface
interface Result {
void print();
}
Result successResult = () -> System.out.println("Success");
Result failResult = () -> System.out.println("Fail");
public void finishExecution(Result funResult) {
// do smth
funResult.print();
}
ref
@
50.
ОСНОВНЫЕ ПОНЯТИЯ STREAM APIStream API — способ работать со структурами
данных в функциональном стиле
Создание стрима
на основе существующей коллекции (с помощью
методов .stream())
из набора данных (с помощью Stream.of())
сгенерировать новый стрим заданного типа
(например, через IntStream.of())
ref
Основные операторы:
промежуточные (например, filter, map)
терминальные (например, count, collect, findFirst)
@
51.
ЗАЧЕМ ИСПОЛЬЗУЕМ?//
• Ускорение обработки данных
• Упрощение обработки данных
/>
• Более читаемый код
• Используем стандартные реализации
основных методов (сортировка,
фильтрация, …)
&
%
ref
@
52.
КОГДА ИСПОЛЬЗОВАТЬ НЕ СТОИТ?//
• Хотим изменить существующую коллекцию,
а не создать новую
• Для создания новой коллекции нужно
использовать много внешних объектов и
зависимых данных
/>
&
• Есть много разных задач,
которые хочется решить за один проход
• Нужно бросать проверяемые исключения при
обработке коллекции
%
ref
@
53.
КАКОЕ ЗНАЧЕНИЕ БУДЕТ ИМЕТЬCOUNTER В РЕЗУЛЬТАТЕ ВЫПОЛНЕНИЯ
КОДА?
public static void counterInStreamTest() {
int counter = 0;
IntStream.range(0, 4).forEach(i -> counter += i);
}
ref
Ответ напишите в чате
@
54.
ИСПОЛЬЗОВАНИЕ ВНЕШНИХОБЪЕКТОВ В STREAM API
В стримах можно использовать:
статические переменные
глобальные переменные
локальные переменные только final и effectively final
Основная причина: защита от проблем параллелизма
ref
@
55.
БУДЕТ ЛИ РАБОТАТЬ ЭТОТ КОД?public void listInStreamTest() {
List<Integer> numbersList = asList(1, 2, 3, 4);
IntStream.range(0, 4)
.forEach(i ->
numbersList.add(numbersList.get(i) + i)
);
}
ref
Ответ напишите в чате
@
56.
СКОЛЬКО ПОТОКОВ ИСПОЛЬЗУЕТСЯПРИ ВЫПОЛНЕНИИ КОДА?
public void parallelStreamTest() {
List<Integer> numbersList = asList(1, 2, 3, 4);
numbersList.parallelStream()
.mapToInt(i -> i + 5)
.forEach(i -> System.out.println("number = " + i));
}
ref
I
1 поток
II
2 потока
III
4 поток
@
57.
ПАРАЛЛЕЛИЗАЦИЯ В STREAM APIПо умолчанию создаваемый поток последовательный.
Чтобы сделать его параллельным, надо использовать
.parallel() для стрима, либо .parallelStream() для объекта.
Для работы используется общий fork-join пул.
Число потоков в пуле = числу процессорных ядер - 1.
Можно переопределить значение через проперти
java.util.concurrent.ForkJoinPool.common.parallelism
(но помним, что переопределение повлияет на все другие
операции, которые также работают с общим пулом)
Важно
Не пытайтесь использовать параллелизацию
везде, это может не ускорить, а замедлить ваш
код или привести к ошибкам. Используем там,
где есть требование к ускорению кода, но
проводим тесты для сравнения результатов
//
/>
&
%
ref
@
58.
СКОЛЬКО ПОТОКОВ ИСПОЛЬЗУЕТСЯПРИ ВЫПОЛНЕНИИ КОДА?
public void parallelStreamTest() {
List<Integer> numbersList = asList(1, 2, 3, 4);
numbersList.parallelStream()
.filter(i -> i != 2)
.mapToInt(i -> i + 5)
.forEachOrdered(i -> System.out.println(
" number = " + i));
}
ref
I
1 поток
II
3 потока
III
4 поток
@
59.
РАЗБИРАЕМСЛОЖНЫЕ
ПРИМЕРЫ
{}
begin
60.
ПИШЕМСТРИМЫ
1
На слайдах будет представлена задача
2
Пробуем написать решение самостоятельно
3
Разбираем правильное решение
Форматы
выполнения:
индивидуально
Написание кода
5 минут
61.
ЗАДАЧА №1Метод, который на вход принимает массив
студентов курса. У студента есть имя,
возраст и номер потока курса,
в котором он принимает участие.
Написать стрим, который возвращает список
уникальных имен студентов возраста от 18 до 30 лет
из второго потока
62.
МОДЕЛЬpublic class Student {
private String name;
private int age;
private Integer groupNumber;
String getName() {
return name;
}
int getAge() {
return age;
}
Integer getGroupNumber() {
return groupNumber;
}
}
63.
ЗАДАЧА №1public List<String> getStudentNames(Student[] students) {
return Arrays.stream(students)
.filter(student -> student.getAge() >= 18 &&
student.getAge() <= 30)
.filter(student -> student.getGroupNumber() == 2)
.map(Student::getName)
.distinct()
.collect(Collectors.toList());
}
64.
ЗАДАЧА №2Метод, который на вход принимает массив
студентов курса. У студента есть имя,
возраст и номер потока курса,
в котором он принимает участие.
Написать стрим, который возвращает максимальный
возраст студента, у которого имя начинается
на букву А или Б и который учится на 1ом потоке,
или выбрасывает исключение с информацией,
что таких студентов нет
65.
ЗАДАЧА №2public int getStudentAgesSummary(Student[] students) throws Exception {
return Arrays.stream(students)
.filter(student -> student.getName().startsWith("А") ||
student.getName().startsWith("Б"))
.filter(student -> student.getGroupNumber() == 1)
.map(Student::getAge)
.max(Comparator.naturalOrder())
.orElseThrow(() -> new Exception("No students present"));
}
66.
Тема 4REFLECTION API
{}
begin
67.
СОДЕРЖАНИЕ• Зачем используем
• Примеры использования
ref
@
5
68.
ГДЕ ПРИМЕНЯЕМ?//
Чтобы узнать информацию об объекте
(класс, модификаторы класса, какие методы есть)
Для получения недоступных полей объекта
Вызов метода по имени
Создание экземпляра класса,
если его тип не известен на этапе компиляции
Изменение свойств объектов и классов
Работа с аннотациями
/>
&
%
ref
@
69.
ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ (1)Создаем в методе экземпляр класса параметризованного типа
public <T> List<T> addNewElement(List<T> elementsList,
Class<T> elemClass)
throws Exception {
T newElement = elemClass.newInstance();
elementsList.add(newElement);
return elementsList;
}
ref
@
70.
ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ (2)Получаем приватную информацию об имене студента
public static class Student {
private String name;
private int age;
private Integer groupNumber;
public Student(String name, int age, Integer groupNumber) {
this.name = name;
this.age = age;
this.groupNumber = groupNumber;
}
int getAge() {
return age;
}
ref
Integer getGroupNumber() {
return groupNumber;
}
}
@
71.
ПРИМЕРЫ ИСПОЛЬЗОВАНИЯПолучаем приватную информацию об имене студента
@Test
public void studentsTest() throws Exception {
StreamExamples.Student newStudent = new StreamExamples.Student(
"Ivan", 30, null);
String studentName = getStudentName(newStudent);
System.out.println("Student name: " + studentName);
}
private String getStudentName(StreamExamples.Student student) throws
Exception {
Field ageField = student.getClass().getDeclaredField("name");
ageField.setAccessible(true);
return (String) ageField.get(student);
}
ref
@
72.
ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ (3)Проверяем информацию из аннотации
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE_USE})
public @interface CourseParticipantAnnotation {
String name() default "creator";
}
@CourseParticipantAnnotation(name = "students")
public class Student {
}
ref
@
73.
ПРИМЕРЫ ИСПОЛЬЗОВАНИЯПроверяем информацию из аннотации
@Test
public void annotationTest() {
CourseParticipantAnnotation annotation = Student.class.
getAnnotation(CourseParticipantAnnotation.class);
System.out.println(annotation.name());
}
ref
@
74.
ЗАВЕРШЕНИЕ//
Напишите в чате:
1
Что было самым полезным
2
Что вы использовали раньше неправильно
3
Чем вы будете теперь пользоваться
/>
&
%
ref
@
75.
СПАСИБОЗА ВНИМАНИЕ
{}
begin