Похожие презентации:
лекция 3 библиотеки даты и времени, Массивы
1. Лекция 3
Массивы + работа с датой и временем2. определение
Массив — это структура данных,хранящая фиксированное количество
элементов одного типа, расположенных в
памяти непрерывно, с доступом по целому
индексу от нуля.
Главное преимущество — доступ за O(1).
Адрес элемента вычисляется по формуле:
• Начало данных + индекс × размер элемента
3. Отличие от c++
в C массив — это указатель на первый элемент, иарифметика указателей позволяет выйти за границы.
В Java массив — полноценный объект в куче:
• Переменная хранит ссылку, а не сами данные.
• У массива есть заголовок с длиной.
• При каждом доступе JVM проверяет границы.
безопасность в обмен на свободу. Запомните это —
дальше всё будет строиться на этом.
4. Объявление, создание и инициализация массивов
Объявление, создание иинициализация массивов
Объявление имеет два способа реализации:
• int[] numbers;
• int numbers[]; ( устаревший вариант который
не стоит использовать в своем коде, но можно
увидеть в учебниках)
Объявление не создаёт массив. Переменная
инициализируется null. Обращение к элементам
даст NullPointerException
5. Объявление, создание и инициализация массивов
Объявление, создание иинициализация массивов
Массив создаётся оператором new:
numbers = new int[5];
JVM выделяет в куче непрерывный блок,
записывает длину в заголовок,
инициализирует элементы значениями по
умолчанию, возвращает ссылку.
6. Объявление, создание и инициализация массивов
Объявление, создание иинициализация массивов
Уже созданные ранее массивы можно
первый раз инициализировать константными
значениям не прибегая повторно к
использованию ключевого слова new
int[] primes = {2, 3, 5, 7, 11};
String[] names = {"Анна", "Борис", "Виктор"};
7. Объявление, создание и инициализация массивов
Объявление, создание иинициализация массивов
Также инициализировать массив
константыми элементами можно уже в
момент его создания, в таком случае нам не
требуется задавать заголовок размера в
ручную
Int [] primes = new int[]{2, 3, 5, 7, 11};
8. Объявление, создание и инициализация массивов
Объявление, создание иинициализация массивов
Если мы хотим инициализировать элемент
массива или переписать его значение уже
после создания в дальнейшем коде, нам
необходимо обратиться к нему по индексу
нужного нам элемента
arr[0] = 99;
9. Устройство массива в памяти JVM
Заголовок объекта1. Слово разметки - 4 байта на 32-битной JVM, 8
байт на 64-битной. Содержит хэш-код, возраст в
поколениях GC, флаг блокировки, указатель на монитор.
2. Указатель на метаданные класса в metaspace - 4 байта
со сжатыми ссылками или 8 байт без них. Сжатые ссылки
включены по умолчанию, если куча меньше 32 ГБ.
3. Заголовок длины массива - 4 байта, Максимальный
размер ограничен Integer.MAX_VALUE (2³¹−1).
10. Устройство массива в памяти JVM
Размер любого объекта кратен 8 байтам.Если после данных остаётся «хвост», JVM
добавляет padding — неиспользуемые байты
в конце.
byte[10] – занимает 10 байт данных, 10 не
кратно 8, система добавляет 6 байт хвоста
11. Как массив распределяется в памяти
В стеке - 4 байта под ссылку.В куче - 40 байт (16 заголовок + 20 данные + 4
padding).
Ссылка в стеке указывает на начало объекта.
12. Как достаем данные из памяти
Процессор читает память кэш-линиями —обычно 64 байта. Одна линия вмещает
16 int или 8 long. При чтении arr[0] в кэш
загружается вся линия — arr[0]…arr[15].
Следующие 15 итераций попадают в быстрый
кэш L1, а не в медленную оперативную
память.
13. Escape-анализ и скаляризация
компилятор HotSpot умеет делать escape-анализ, он проверяет,что если массив создаётся внутри метода, не возвращается наружу
и не сохраняется в поле, компилятор может скаляризовать его —
заменить на отдельные переменные в регистрах без выделения
памяти в куче.
int sum(int a, int b) {
int[] temp = {a, b};
return temp[0] + temp[1];
}
JIT компилятор может полностью устранить массив. Но это
работает только для простых локальных случаев.
14. Вопросы для закрепления
Вопрос 1: сколько байт занимает double[100]?(1 дабл = 8 байт)
Вопрос 2: почему int[0] занимает 16 байт?
Вопрос 3: когда массив может не попасть в
кучу?
15. Копирование массивов
Копирование массивовПрисваивание int[] b = a; копирует ссылку, а не
массив. Изменение через b видно через a
Если мы хотим создать действительно копию
массива без вреда для оригинального то самый
быстрый способ будет:
int[] source = {1, 2, 3, 4, 5};
int[] dest = new int[5];
System.arraycopy(source, 0, dest, 0, source.length);
16. Остальные методы копирования
int[] copy = original.clone(); (поверхностнаякопия, в случае строк скопирует лишь ссылки)
Если нам нужно скопировать не весь массив а
только определенный диапазон то
применяют методы:
int[] extended = Arrays.copyOf(original, 10);
int[] range = Arrays.copyOfRange(original, 1, 4);
17. Как создать уникальный метод копирования
for (int i = 0; i < original.length; i++) {if (ваше нужное условие)
deepCopy[i] = original[i].clone();
}
18. Класс Arrays — методы работы с массивами
Класс Arrays — методы работы смассивами
Arrays.toString() / deepToString() – представление значений массива в виде строки
Arrays.sort() – сортировка массива, можно отсортировать только конкретый диапазон
указав его
Arrays.parallelSort() – также сортировка, но уже гораздо быстрее без возможности указать
диапазон
Arrays.binarySearch() – ищет индекс определенного значения, но только в
отсортированном массиве
Arrays.equals() / deepEquals() – проверка равенства элементов массива с чем либо
Arrays.fill() – заполняет массив или указанный диапазон массива определенным
значением
19. Класс Arrays — методы работы с массивами
Класс Arrays — методы работы смассивами
Arrays.stream() — поток для функциональной обработки всего массива.
Например : int sum = Arrays.stream(new int[]{1, 2, 3}).sum();
Arrays.setAll() – заполняет массив значениями полученными из функции что в
него передали, например Arrays.setAll(squares, i -> i * i); вернет массив [0, 1, 4, 9,
16]
Arrays.compare() – возвращает логическое да или логическое нет о равенстве 2
массивов
Arrays.hashCode() – генерация хэш значения для массива на основе его адреса
20. Многомерные массивы
В Java нет настоящих многомерныхмассивов. int[][] — это массив ссылок на int[].
int[][] matrix = new int[3][4];
первое число отвечает за строки, второе за
столбцы
21. Инициализация многомерного массива
int[][] matrix = {{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
Для обхода таких массивов, необходим
вложенный цикл
22. Подводный камень многомерных массивов
каждый подмассив — отдельный объект, онимогут быть не рядом в куче. Что может
отрицательно влиять на производительности
работы с ним, но упрощать основное
ограничение массивов в лице зависимости от
соседства ячеек памяти
23. Транспонирование
int[][] transpose(int[][] m) {int rows = m.length, cols = m[0].length;
int[][] result = new int[cols][rows];
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
result[j][i] = m[i][j];
return result;
}
24. Ковариантность, generics и varargs
Ковариантность, generics и varargsВ Java массивы ковариантны, это значит что
если S — подтип T, то S[] — подтип T[]. Но при
этом параметризированные типы данных
инвариативны, в связи с чем если изначально
тип данных массива не был указан конкретно,
ковариативность невозможна
25. Ковариантность, параметризированный тип и varargs
Ковариантность,параметризированный тип и varargs
В Java массивы ковариантны, это значит что если S —
подтип T, то S[] — подтип T[].
Но при этом параметризированные типы данных
инвариативны, в связи с чем если изначально тип данных
массива не был указан конкретно, ковариативность
невозможна
Varargs (T... args) в Java технически реализованы как
массив. То есть сигнатура:
void foo(String... args)
равна
void foo(String[] args)
26. Практикум
ПрактикумЗадание: написать программу, которая
запрашивает размер массива, заполняет его
числами с клавиатуры, выводит
через Arrays.toString, сортирует, находит
сумму элементов и максимальный элемент
27. Работа с датой и временем
В старых версиях джавы использоваласьбиблиотека java.util.Date с ним можно
ознакомиться для общего развития но в коде
он более не применяется
Актуальной библиотекой для работы сейчас
является java.time
28. Основные классы библиотеки
Instant - на шкале времени (UTC), точность до наносекундLocalDate - Дата без времени и зоны (год-месяц-день)
LocalTime - Время без даты и зоны (часы-минуты-секунды-наносекунды)
LocalDateTime - Дата и время без зоны
ZonedDateTime -Дата и время с часовым поясом
OffsetDateTime - Дата и время со смещением от UTC
OffsetTime - Время со смещением
ZoneId - Идентификатор часового пояса
ZoneOffset - Смещение от UTC
Duration
- Промежуток времени в секундах/наносекундах
Period - Промежуток в годах/месяцах/днях
DateTimeFormatter - Форматирование и парсинг
Clock - Источник текущего времени (удобно для тестов)
29. Instant
InstantInstant — это точка на временной шкале, всегда в UTC.
Instant хранит два числа: количество секунд с эпохи Unix и
количество наносекунд внутри текущей секунды. Это
позволяет представлять время с точностью до наносекунд
— миллиардной доли секунды.
Instant now = Instant.now();
Этот объект не знает ни о годах, ни о месяцах, ни о
часовых поясах. Он просто говорит: «прошло вот столько
секунд и наносекунд с 1 января 1970 года».
30. LocalDate, LocalTime, LocalDateTime
LocalDate, LocalTime, LocalDateTimeЭти три класса представляют время так, как
его видит человек, — но без привязки к
часовому поясу.
LocalDate — только дата
• LocalDate today = LocalDate.now();
• LocalDate birthday = LocalDate.of(1995, 7,
12);
• LocalDate parsed = LocalDate.parse("2024-0315");
31. LocalDate
LocalDate date = LocalDate.of(2024, 3, 15);int year = date.getYear();
// 2024
int month = date.getMonthValue(); // 3
Month monthEnum = date.getMonth(); // MARCH
int day = date.getDayOfMonth(); // 15
DayOfWeek dow = date.getDayOfWeek(); // FRIDAY
int dayOfYear = date.getDayOfYear(); // 75 (15 марта — 75-й
день года)
boolean leap = date.isLeapYear();
int daysInMonth = date.lengthOfMonth();
32. LocalDate
LocalDate today = LocalDate.of(2024, 3, 15);• LocalDate tomorrow = today.plusDays(1);
• LocalDate nextMonth = today.plusMonths(1);
• LocalDate lastYear = today.minusYears(1);
• today.isBefore(tomorrow );
• today.isAfter(tomorrow );
• today.isEqual(tomorrow );
33. LocalTime
LocalTimeВнутри LocalTime хранит часы, минуты, секунды и наносекунды.
LocalTime time = LocalTime.of(14, 30, 45);
int hour = time.getHour(); // 14
int minute = time.getMinute(); // 30
int second = time.getSecond(); // 45
int nano = time.getNano(); // 0
LocalTime plusHour = time.plusHours(1); // 15:30:45
LocalTime minusMin = time.minusMinutes(15); // 14:15:45
truncatedTo(ChronoUnit.SECONDS) — отбрасывает всё, что меньше указанной
единицы:
34. LocalDateTime
Это комбинация LocalDate и LocalTime. Хранитгод, месяц, день, часы, минуты, секунды,
наносекунды. Но без часового пояса.
Методы все такие же как у дочерних классов
рассмотренных ранее
35. ZonedDateTime
Это LocalDateTime плюс часовой пояс. Он знает, что «15марта 2024, 14:30» произошло именно в Москве, а не в
Нью-Йорке. Это делает его полноценным представлением
момента времени, эквивалентным Instant, но с
календарной информацией.
Часовой пояс в Java представлен классом ZoneId.
Идентификаторы зон — это строки
вида Europe/Moscow, America/New_York, Asia/Tokyo
ZoneId moscow = ZoneId.of("Europe/Moscow");
ZonedDateTime now = ZonedDateTime.now(moscow);
36. Переход между часовыми поясами
ZonedDateTime moscow =ZonedDateTime.now(ZoneId.of("Europe/Moscow"))
;
ZonedDateTime tokyo =
moscow.withZoneSameInstant(ZoneId.of("Asia/Tok
yo"));
Метод withZoneSameInstant сохраняет момент и
меняет зону. Если в Москве 12:00, то в Токио
будет 18:00 — тот же момент, разные часы.
37. OffsetDateTime и OffsetTime
OffsetDateTime и OffsetTimeИногда у вас нет полной информации о зоне — только
смещение от UTC. Например, сервер прислал
время 2024-03-15T14:30:00+03:00. Вы не знаете,
Москва это или Стамбул — обе зоны имеют +03:00.
Для таких случаев есть OffsetDateTime.
OffsetDateTime odt = OffsetDateTime.now();
OffsetDateTime parsed = OffsetDateTime.parse("202403-15T14:30:00+03:00");
ZoneOffset offset = odt.getOffset(); // +03:00
38. Duration
Duration представляет точное количествовремени — секунды и наносекунды. Он не знает
о календаре. Подходит для измерения «сколько
прошло времени между двумя моментами».
Instant start = Instant.now(); // ... какая-то
работа ...
Instant end = Instant.now();
Duration duration = Duration.between(start, end);
39. Period
PeriodВсе точно также как и duration но разницу
измеряет уже не в секундах а днях и месяцах
LocalDate birth = LocalDate.of(1990, 5, 20);
LocalDate today = LocalDate.now();
Period age = Period.between(birth, today);
System.out.println(age.getYears() + " лет, "
+ age.getMonths() + " месяцев, "
+ age.getDays() + " дней");
40. практика
Сколько дней до Нового года?LocalDate today = LocalDate.now();
LocalDate newYear = LocalDate.of(today.getYear() +
1, 1, 1);
long days = ChronoUnit.DAYS.between(today,
newYear);
System.out.println("До Нового года: " + days + "
дней");