История IT-технологий сегодня — 10 Февраля
ℹ️ Кто родился в этот день
Уолтер Хаузер Браттейн (англ. Walter Houser Brattain; 10 февраля 1902 — 13 октября 1987) — американский физик, лауреат Нобелевской премии по физике в 1956 году «за исследования полупроводников и открытие транзисторного эффекта» (совместно с Уильямом Брэдфордом Шокли и Джоном Бардином).
🌐 Знаковые события
1996 — начался первый шахматный матч между суперкомпьютером IBM Deep Blue и Гарри Каспаровым (со счётом 4—2 победил Г. Каспаров).
2009 — на орбите Земли произошло первое столкновение искусственных спутников за всю историю космонавтики. Столкновение произошло над территорией Российской Федерации (над полуостровом Таймыр, над точкой 72,5° с. ш., 97,9° в. д.), на высоте 788,6 километра. Два спутника во время вращения вокруг Земли со скоростью около 7,5 км/с столкнулись на относительной скорости свыше 10 км/с. Искусственные спутники — «Космос-2251», принадлежавший Космическим войскам России, выведенный на орбиту в 1993 году и функционировавший до 1995 года, и Iridium 33, один из 72 спутников международного оператора спутниковой телефонной связи «Иридиум», запущенный на орбиту в 1997 году, в результате столкновения разрушились полностью. Масса американского спутника «Иридиум» составляла 600 кг, а российского аппарата «Космос-2251» — 900 кг. В результате столкновения образовалось около 600 обломков.
#Biography #Birth_Date #Events #10февраля
Уолтер Хаузер Браттейн (англ. Walter Houser Brattain; 10 февраля 1902 — 13 октября 1987) — американский физик, лауреат Нобелевской премии по физике в 1956 году «за исследования полупроводников и открытие транзисторного эффекта» (совместно с Уильямом Брэдфордом Шокли и Джоном Бардином).
1996 — начался первый шахматный матч между суперкомпьютером IBM Deep Blue и Гарри Каспаровым (со счётом 4—2 победил Г. Каспаров).
2009 — на орбите Земли произошло первое столкновение искусственных спутников за всю историю космонавтики. Столкновение произошло над территорией Российской Федерации (над полуостровом Таймыр, над точкой 72,5° с. ш., 97,9° в. д.), на высоте 788,6 километра. Два спутника во время вращения вокруг Земли со скоростью около 7,5 км/с столкнулись на относительной скорости свыше 10 км/с. Искусственные спутники — «Космос-2251», принадлежавший Космическим войскам России, выведенный на орбиту в 1993 году и функционировавший до 1995 года, и Iridium 33, один из 72 спутников международного оператора спутниковой телефонной связи «Иридиум», запущенный на орбиту в 1997 году, в результате столкновения разрушились полностью. Масса американского спутника «Иридиум» составляла 600 кг, а российского аппарата «Космос-2251» — 900 кг. В результате столкновения образовалось около 600 обломков.
#Biography #Birth_Date #Events #10февраля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Раздел 8. Stream API и функциональный стиль в Java
Глава 1: Философский фундамент. От шагов к преобразованиям
Практика: Рефакторинг мышления в «Библиотеке»
Задача: Найти книги автора «X», отсортировать по году издания, вернуть названия 3 самых старых.
Stream API и функциональный стиль в Java, это один из самых мощных инструментов современного Java, который позволяет писать код более выразительно, лаконично и эффективно. Но прежде чем погружаться в синтаксис Stream, важно понять философский фундамент: переход от императивного стиля (шаг за шагом, с управлением состоянием) к декларативному (описание, что нужно, без деталей как).
Сегодня мы проведем рефакторинг мышления на примере проекта «Библиотека»: решим задачу поиска книг автора "X", сортировки по году и возврата названий 3 самых старых. Мы сделаем это в два шага — императивно и декларативно (мысленно), чтобы вы почувствовали разницу.
Подготовка к уроку
Перед началом убедитесь, что ваш проект «Библиотека» готов: класс Book с полями title, author, year и геттерами, класс Library с List<Book> books и методами добавления/вывода. Добавьте 10–15 книг с разными авторами, включая автора "X" с минимум 5 книгами разных годов.
Импортируйте пакеты: В Library.java импортируйте java.util.Comparator, java.util.ArrayList.
Задача — фильтрация, сортировка, отображение и ограничение. Императивно — шаг за шагом с временными коллекциями. Декларативно — описание цепочки преобразований.
Шаг 1: Императивный подход
В императивном стиле вы описываете "как" сделать: создаёте временные структуры, управляете циклами, изменяете состояние.
Создайте метод findOldestBooksByAuthorImperative(String author, int limit) в Library:
Возвращает List<String> — названия limit самых старых книг автора.
Создайте временный List<Book> filteredBooks = new ArrayList<>();.
Переберите books: for (Book b : books) if (b.getAuthor().equals(author)) filteredBooks.add(b);.
Отсортируйте filteredBooks по году: filteredBooks.sort(Comparator.comparingInt(Book::getYear)); (по возрастанию — самые старые сначала).
Создайте результат List<String> titles = new ArrayList<>();.
Переберите filteredBooks: for (int i = 0; i < Math.min(limit, filteredBooks.size()); i++) titles.add(filteredBooks.get(i).getTitle());.
Верните titles.
Тестирование:
Вызовите с author = "X", limit = 3 — получите 3 самых старых названия.
Проверьте на пустом списке или без книг автора — вернёт пустой list.
Анализ императивного подхода (объёмно):
2 временных коллекции: filteredBooks (для фильтра) и titles (для отображения) — overhead памяти O(n).
3 точки изменения состояния: add в filtered, sort (мутирует list), add в titles — каждая может вызвать ошибки (null, index out of bounds).
Явное управление индексами: Math.min и i < limit — ручной контроль, error-prone (off-by-one).
Процессы внутри:
Фильтр: O(n) перебор, add O(1).
Sort: Timsort O(n log n), мутирует.
Отображение: O(limit) цикл.
Ловушки: Если books изменяется во время перебора — ConcurrentModificationException; sort по году ascending — для "старых" (маленький год) правильно.
Преимущества: Ясно "как" работает, контроль.
Недостатки: Verbose, mutable state, трудно parallelize.
#Java #для_новичков #beginner #Практика #stream_api #declarative
Глава 1: Философский фундамент. От шагов к преобразованиям
Практика: Рефакторинг мышления в «Библиотеке»
Задача: Найти книги автора «X», отсортировать по году издания, вернуть названия 3 самых старых.
Stream API и функциональный стиль в Java, это один из самых мощных инструментов современного Java, который позволяет писать код более выразительно, лаконично и эффективно. Но прежде чем погружаться в синтаксис Stream, важно понять философский фундамент: переход от императивного стиля (шаг за шагом, с управлением состоянием) к декларативному (описание, что нужно, без деталей как).
Сегодня мы проведем рефакторинг мышления на примере проекта «Библиотека»: решим задачу поиска книг автора "X", сортировки по году и возврата названий 3 самых старых. Мы сделаем это в два шага — императивно и декларативно (мысленно), чтобы вы почувствовали разницу.
Подготовка к уроку
Перед началом убедитесь, что ваш проект «Библиотека» готов: класс Book с полями title, author, year и геттерами, класс Library с List<Book> books и методами добавления/вывода. Добавьте 10–15 книг с разными авторами, включая автора "X" с минимум 5 книгами разных годов.
Импортируйте пакеты: В Library.java импортируйте java.util.Comparator, java.util.ArrayList.
Задача — фильтрация, сортировка, отображение и ограничение. Императивно — шаг за шагом с временными коллекциями. Декларативно — описание цепочки преобразований.
Шаг 1: Императивный подход
В императивном стиле вы описываете "как" сделать: создаёте временные структуры, управляете циклами, изменяете состояние.
Создайте метод findOldestBooksByAuthorImperative(String author, int limit) в Library:
Возвращает List<String> — названия limit самых старых книг автора.
Создайте временный List<Book> filteredBooks = new ArrayList<>();.
Переберите books: for (Book b : books) if (b.getAuthor().equals(author)) filteredBooks.add(b);.
Отсортируйте filteredBooks по году: filteredBooks.sort(Comparator.comparingInt(Book::getYear)); (по возрастанию — самые старые сначала).
Создайте результат List<String> titles = new ArrayList<>();.
Переберите filteredBooks: for (int i = 0; i < Math.min(limit, filteredBooks.size()); i++) titles.add(filteredBooks.get(i).getTitle());.
Верните titles.
Тестирование:
Вызовите с author = "X", limit = 3 — получите 3 самых старых названия.
Проверьте на пустом списке или без книг автора — вернёт пустой list.
Анализ императивного подхода (объёмно):
2 временных коллекции: filteredBooks (для фильтра) и titles (для отображения) — overhead памяти O(n).
3 точки изменения состояния: add в filtered, sort (мутирует list), add в titles — каждая может вызвать ошибки (null, index out of bounds).
Явное управление индексами: Math.min и i < limit — ручной контроль, error-prone (off-by-one).
Процессы внутри:
Фильтр: O(n) перебор, add O(1).
Sort: Timsort O(n log n), мутирует.
Отображение: O(limit) цикл.
Ловушки: Если books изменяется во время перебора — ConcurrentModificationException; sort по году ascending — для "старых" (маленький год) правильно.
Преимущества: Ясно "как" работает, контроль.
Недостатки: Verbose, mutable state, трудно parallelize.
#Java #для_новичков #beginner #Практика #stream_api #declarative
👍4
Шаг 2: Декларативный подход (мысленно)
В декларативном стиле вы описываете "что" нужно: цепочку преобразований данных, без деталей реализации. Это фундамент Stream API — думайте о данных как о потоке, который фильтруется, сортируется, отображается.
Мысленно опишите цепочку в комментариях метода findOldestBooksByAuthorDeclarative(String author, int limit):
Фильтр: Выбрать книги, где author == "X".
Сортировка: Упорядочить по году издания (ascending для старых).
Отображение: Преобразовать в названия (title).
Ограничение: Взять первые 3.
Не пишите код — только подумайте и запишите в комментарии, как это выглядело бы декларативно (в стиле Stream, но без синтаксиса).
Тестирование: Не нужно — это мысленный рефакторинг.
Анализ декларативного подхода (объёмно):
Нет временных коллекций: Цепочка преобразований на потоке — lazy, intermediate operations не создают полные списки.
Нет изменения состояния: Immutable pipeline — данные не мутируются, только преобразуются.
Нет индексов: Ограничение limit(3) — declarative, без ручного Math.min.
Процессы внутри: Filter O(n), sort O(n log n), map O(n), limit O(1).
Ловушки: Lazy evaluation — sort не выполняется, пока не terminal operation (limit).
Преимущества: Кратко, читаемо, легко паралелить (stream().parallel()).
Недостатки: Трудно дебажить (intermediate steps hidden), overhead для малого n.
Вывод: Декларативный подход заставляет думать о данных как о целом (поток), а не об отдельных элементах (циклы). Это рефакторит мышление к функциональному стилю, где фокус на "что", а не "как".
Тестирование и отладка
Императивный метод: Добавьте 10 книг, вызовите — проверьте результат.
Декларативный: Подумать, как цепочка упростит код (меньше строк, меньше ошибок).
Сравнение: Замерьте время для 1000 книг — императивный vs мысленный (для декларативного — представьте Stream).
Полезные советы для новичков
Императив: Для низкоуровневого программирования и высокого контроля кода.
Декларатив: Для более высокого уровня программирования и читабельности.
Рефакторинг: Начните с императивного вида, перейдите к декларативному.
Практическое задание
Реализуйте императивный метод.
Опишите декларативно в комментариях.
Добавьте задачу: Найти 5 самых новых книг жанра "Y" — в двух стилях.
#Java #для_новичков #beginner #Практика #stream_api #declarative
В декларативном стиле вы описываете "что" нужно: цепочку преобразований данных, без деталей реализации. Это фундамент Stream API — думайте о данных как о потоке, который фильтруется, сортируется, отображается.
Мысленно опишите цепочку в комментариях метода findOldestBooksByAuthorDeclarative(String author, int limit):
Фильтр: Выбрать книги, где author == "X".
Сортировка: Упорядочить по году издания (ascending для старых).
Отображение: Преобразовать в названия (title).
Ограничение: Взять первые 3.
Не пишите код — только подумайте и запишите в комментарии, как это выглядело бы декларативно (в стиле Stream, но без синтаксиса).
Тестирование: Не нужно — это мысленный рефакторинг.
Анализ декларативного подхода (объёмно):
Нет временных коллекций: Цепочка преобразований на потоке — lazy, intermediate operations не создают полные списки.
Нет изменения состояния: Immutable pipeline — данные не мутируются, только преобразуются.
Нет индексов: Ограничение limit(3) — declarative, без ручного Math.min.
Процессы внутри: Filter O(n), sort O(n log n), map O(n), limit O(1).
Ловушки: Lazy evaluation — sort не выполняется, пока не terminal operation (limit).
Преимущества: Кратко, читаемо, легко паралелить (stream().parallel()).
Недостатки: Трудно дебажить (intermediate steps hidden), overhead для малого n.
Вывод: Декларативный подход заставляет думать о данных как о целом (поток), а не об отдельных элементах (циклы). Это рефакторит мышление к функциональному стилю, где фокус на "что", а не "как".
Тестирование и отладка
Императивный метод: Добавьте 10 книг, вызовите — проверьте результат.
Декларативный: Подумать, как цепочка упростит код (меньше строк, меньше ошибок).
Сравнение: Замерьте время для 1000 книг — императивный vs мысленный (для декларативного — представьте Stream).
Полезные советы для новичков
Императив: Для низкоуровневого программирования и высокого контроля кода.
Декларатив: Для более высокого уровня программирования и читабельности.
Рефакторинг: Начните с императивного вида, перейдите к декларативному.
Практическое задание
Реализуйте императивный метод.
Опишите декларативно в комментариях.
Добавьте задачу: Найти 5 самых новых книг жанра "Y" — в двух стилях.
#Java #для_новичков #beginner #Практика #stream_api #declarative
👍4
Что выведет код?
#Tasks
import java.util.Optional;
public class Task100226 {
public static void main(String[] args) {
Optional<String> opt = Optional.ofNullable(null)
.map(s -> s.toString())
.or(() -> Optional.of("DEFAULT"))
.filter(s -> s.length() > 3);
System.out.println(opt.orElse("FALLBACK"));
}
}
#Tasks
👍2
👍2
Объясните, что такое потокобезопасность (thread safety). Как ее достичь? 🤓
Ответ:
Потокобезопасность — это свойство объекта или кода корректно работать в условиях многопоточного доступа, когда несколько потоков выполняют его одновременно.
Без синхронизации это может привести к состоянию гонки (race condition) и повреждению данных.
Основные способы достижения:
1) Использование synchronized методов или блоков.
2) Использование классов из java.util.concurrent (например, ConcurrentHashMap, AtomicInteger).
3) Использование неизменяемых (immutable) объектов.
4) Ограничение доступа к общим данным (локальные переменные, ThreadLocal).
#собеседование
Ответ:
Потокобезопасность
Без синхронизации это может привести к состоянию гонки (race condition) и повреждению данных.
Основные способы достижения:
1) Использование synchronized методов или блоков.
2) Использование классов из java.util.concurrent (например, ConcurrentHashMap, AtomicInteger).
3) Использование неизменяемых (immutable) объектов.
4) Ограничение доступа к общим данным (локальные переменные, ThreadLocal).
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
История IT-технологий сегодня — 11 Февраля
ℹ️ Кто родился в этот день
То́мас А́лва Э́дисон (англ. Thomas Alva Edison; 11 февраля 1847, Майлан, штат Огайо — 18 октября 1931, Уэст-Ориндж, штат Нью-Джерси) — американский инженер, изобретатель и предприниматель. Создатель фонографа; усовершенствовал телеграф, телефон, киноаппаратуру, разработал один из первых коммерчески успешных вариантов электрической лампы накаливания. Получил в США 1093 патента и около 3 тысяч — в других странах мира.
Ричард Уэсли Хэмминг (11 февраля 1915 года, Чикаго — 7 января 1998 года, Монтерей) — американский математик, работы которого в сфере теории информации оказали существенное влияние на компьютерные науки и телекоммуникации. Основной вклад — т. н. код Хэмминга, а также расстояние Хэмминга.
🌐 Знаковые события
1970 — выведен на орбиту первый японский искусственный спутник Земли «Осуми».
2001 — создан компьютерный вирус Anna Kournikova. Он предлагал пользователям открыть почтовое сообщение, в котором предположительно было изображение Анны Курниковой, хотя на самом деле там была вредоносная программа. Если это удавалось, программа рассылала себя всем контактам в адресной книге Microsoft Outlook. Червь отправлял сообщение: «Привет: Посмотри на это!» с прикрепленным файлом «AnnaKournikova.jpg.vbs». При запуске файл не отображал фотографию Анны Курниковой, вместо этого запуская скрипт на Visual Basic, который пересылал себя всем контактам в адресной книге жертвы. Червь был создан с использованием простой и широко доступной программы на Visual Basic «Worm Generator», разработанной аргентинским программистом под ником «[K]Alamar». Похожий на вирус «ILOVEYOU» 2000 года, червь «Anna Kournikova» не портил данные на зараженном компьютере.
#Biography #Birth_Date #Events #11февраля
То́мас А́лва Э́дисон (англ. Thomas Alva Edison; 11 февраля 1847, Майлан, штат Огайо — 18 октября 1931, Уэст-Ориндж, штат Нью-Джерси) — американский инженер, изобретатель и предприниматель. Создатель фонографа; усовершенствовал телеграф, телефон, киноаппаратуру, разработал один из первых коммерчески успешных вариантов электрической лампы накаливания. Получил в США 1093 патента и около 3 тысяч — в других странах мира.
Ричард Уэсли Хэмминг (11 февраля 1915 года, Чикаго — 7 января 1998 года, Монтерей) — американский математик, работы которого в сфере теории информации оказали существенное влияние на компьютерные науки и телекоммуникации. Основной вклад — т. н. код Хэмминга, а также расстояние Хэмминга.
1970 — выведен на орбиту первый японский искусственный спутник Земли «Осуми».
2001 — создан компьютерный вирус Anna Kournikova. Он предлагал пользователям открыть почтовое сообщение, в котором предположительно было изображение Анны Курниковой, хотя на самом деле там была вредоносная программа. Если это удавалось, программа рассылала себя всем контактам в адресной книге Microsoft Outlook. Червь отправлял сообщение: «Привет: Посмотри на это!» с прикрепленным файлом «AnnaKournikova.jpg.vbs». При запуске файл не отображал фотографию Анны Курниковой, вместо этого запуская скрипт на Visual Basic, который пересылал себя всем контактам в адресной книге жертвы. Червь был создан с использованием простой и широко доступной программы на Visual Basic «Worm Generator», разработанной аргентинским программистом под ником «[K]Alamar». Похожий на вирус «ILOVEYOU» 2000 года, червь «Anna Kournikova» не портил данные на зараженном компьютере.
#Biography #Birth_Date #Events #11февраля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
[Совет по Java #004]
Тема: При сравнении строк, которые могут быть null, вызывайте equals на константе или используйте Objects.equals().
Проблема: Вызов метода equals(Object) на потенциально null-ссылке приводит к выбрасыванию исключения NullPointerException (NPE).
Это классическая ошибка, возникающая при сравнении переменной, полученной извне (например, из пользовательского ввода, базы данных или API), с ожидаемым строковым литералом. Разработчик, вызывая variable.equals("CONST"), предполагает, что результатом будет false, если строки не равны, но в случае, когда variable равна null, поток выполнения прерывается неконтролируемым исключением. Такая ситуация нарушает принцип устойчивости (robustness) кода и требует дополнительных проверок, что увеличивает когнитивную нагрузку и загромождает логику условными операторами.
Решение: Существуют две основные идиомы, позволяющие безопасно сравнивать строки при возможном null-значении.
1. Вызов метода equals на известной, гарантированно не-null константе или литерале: "CONST".equals(variable).
2. Использование статического утилитного метода java.util.Objects.equals(Object a, Object b), который был введен в Java 7 специально для безопасного сравнения двух объектов, каждый из которых может быть null. Этот метод реализует сравнение с полной проверкой на null и возвращает true, если оба аргумента null, или результат вызова a.equals(b) в ином случае.
Объяснение: Вызов "CONST".equals(variable) является защищенным, потому что литерал "CONST" — это валидный, существующий в пуле строк объект, на котором можно безопасно вызвать любой метод.
Его реализация equals включает проверку на null для переданного аргумента. Метод Objects.equals() абстрагирует эту логику, делая код более симметричным и читаемым, особенно при сравнении двух переменных, каждая из которых может быть null. Это универсальное решение, применимое не только к строкам, но и к любым объектам. Важно подчеркнуть, что для случая, когда null считается неравным любому значению (включая другой null), необходимо использовать явную проверку variable != null && variable.equals(constant).
Однако в большинстве сценариев логического сравнения Objects.equals() предоставляет корректную и безопасную семантику.
#Java #советы
Тема: При сравнении строк, которые могут быть null, вызывайте equals на константе или используйте Objects.equals().
Проблема: Вызов метода equals(Object) на потенциально null-ссылке приводит к выбрасыванию исключения NullPointerException (NPE).
Это классическая ошибка, возникающая при сравнении переменной, полученной извне (например, из пользовательского ввода, базы данных или API), с ожидаемым строковым литералом. Разработчик, вызывая variable.equals("CONST"), предполагает, что результатом будет false, если строки не равны, но в случае, когда variable равна null, поток выполнения прерывается неконтролируемым исключением. Такая ситуация нарушает принцип устойчивости (robustness) кода и требует дополнительных проверок, что увеличивает когнитивную нагрузку и загромождает логику условными операторами.
Решение: Существуют две основные идиомы, позволяющие безопасно сравнивать строки при возможном null-значении.
1. Вызов метода equals на известной, гарантированно не-null константе или литерале: "CONST".equals(variable).
2. Использование статического утилитного метода java.util.Objects.equals(Object a, Object b), который был введен в Java 7 специально для безопасного сравнения двух объектов, каждый из которых может быть null. Этот метод реализует сравнение с полной проверкой на null и возвращает true, если оба аргумента null, или результат вызова a.equals(b) в ином случае.
import java.util.Objects;
public class SafeStringComparison {
public static void main(String[] args) {
String constantValue = "EXPECTED_VALUE";
String variableFromExternalSource = getPossiblyNullString(); // Может вернуть null
//Антипаттерн: Риск NullPointerException.
try {
boolean unsafeResult = variableFromExternalSource.equals(constantValue);
} catch (NullPointerException e) {
System.out.println("NPE: Прямой вызов equals на null-переменной.");
}
//Решение 1: Вызов equals() на строковой константе.
boolean safeResult1 = constantValue.equals(variableFromExternalSource);
System.out.println("Сравнение через константу: " + safeResult1); // Безопасно вернет false.
//Решение 2: Использование Objects.equals().
boolean safeResult2 = Objects.equals(constantValue, variableFromExternalSource);
System.out.println("Сравнение через Objects.equals(): " + safeResult2); // Также безопасно.
// Пример с двумя null-значениями:
String nullString = null;
boolean resultForTwoNulls = Objects.equals(nullString, null); // Возвращает true.
System.out.println("Objects.equals(null, null): " + resultForTwoNulls);
}
private static String getPossiblyNullString() {
// Имитация логики, которая может вернуть null.
return Math.random() > 0.5 ? "SOME_VALUE" : null;
}
}
Объяснение: Вызов "CONST".equals(variable) является защищенным, потому что литерал "CONST" — это валидный, существующий в пуле строк объект, на котором можно безопасно вызвать любой метод.
Его реализация equals включает проверку на null для переданного аргумента. Метод Objects.equals() абстрагирует эту логику, делая код более симметричным и читаемым, особенно при сравнении двух переменных, каждая из которых может быть null. Это универсальное решение, применимое не только к строкам, но и к любым объектам. Важно подчеркнуть, что для случая, когда null считается неравным любому значению (включая другой null), необходимо использовать явную проверку variable != null && variable.equals(constant).
Однако в большинстве сценариев логического сравнения Objects.equals() предоставляет корректную и безопасную семантику.
#Java #советы
👍7
Что выведет код?
#Tasks
import java.util.*;
public class Task110226 {
public static void main(String[] args) {
String str = null;
List<String> list = new ArrayList<>();
System.out.println(str == null);
System.out.println("null".equals(str));
System.out.println(Objects.equals(str, "test"));
System.out.println(list.equals(str));
}
}
#Tasks
👍4
Варианты ответа:
Anonymous Quiz
8%
true false false true
25%
true true false false
58%
true false false false
8%
true true true false
👍2
В чем разница между sleep() и wait()? 🤓
Ответ:
Thread.sleep(long millis) — статический метод, который приостанавливает выполнение текущего потока на указанное время, не освобождая при этом захваченные мониторы (lock).
Object.wait() — метод экземпляра, который также приостанавливает поток, но освобождает монитор объекта, на котором он вызван.
Поток может быть пробужден досрочно через notify()/notifyAll(). wait() используется для кооперации между потоками, а sleep() — просто для задержки.
#собеседование
Ответ:
Thread.sleep(long millis)
Object.wait() — метод экземпляра, который также приостанавливает поток, но освобождает монитор объекта, на котором он вызван.
Поток может быть пробужден досрочно через notify()/notifyAll(). wait() используется для кооперации между потоками, а sleep() — просто для задержки.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
История IT-технологий сегодня — 12 Февраля
ℹ️ Кто родился в этот день
Чарлз Ро́берт Да́рвин (англ. Charles Robert Darwin, английское произношение: [tʃɑːlz 'dɑːwɪn]; 12 февраля 1809, Шрусбери, Шропшир — 19 апреля 1882, Даун Хаус[вд]) — английский биолог-эволюционист, зоолог, ботаник, палеонтолог, геолог; натуралист и путешественник; Одним из первых пришёл к выводу и обосновал идею о том, что все виды живых организмов эволюционируют со временем и происходят от общих предков. Развёрнутое изложение теории было опубликовано в 1859 году в книге «Происхождение видов».
Рэймонд Курцвейл (англ. Raymond Kurzweil; род. 12 февраля 1948, Нью-Йорк, США) — американский изобретатель и футуролог. Создатель многочисленных систем для распознавания речи. Известен научными технологическими прогнозами, учитывающими появление искусственного интеллекта и средств радикального продления жизни людей. Согласно Курцвейлу, в будущем человечество достигнет почти неограниченного материального изобилия, а люди могут стать бессмертными. Он также дал обоснование технологической сингулярности — феноменально быстрого научно-технического прогресса, основанного на мощном искусственном интеллекте (превосходящем человеческий) и киборгизации людей.
Эмилий Христианович Ленц (при рождении Генрих Фридрих Эмиль Ленц, нем. Heinrich Friedrich Emil Lenz; 12 (24) февраля 1804, Дерпт — 29 января (10 февраля) 1865, Рим) — российский физик немецкого происхождения; является одним из основоположников электротехники. С его именем связано открытие закона, определяющего тепловые действия тока, и закона, определяющего направление индукционного тока.
🌐 Знаковые события
1961 — в Советском Союзе в сторону планеты Венера запущена автоматическая межпланетная станция «Венера-1». «Венера-1» стала первым космическим аппаратом, пролетевшим на близком расстоянии от планеты Венера.
2001 – космический аппарат NEAR Shoemaker совершил посадку в «седловидной» области астероида 433 Эрос , став первым космическим аппаратом, совершившим посадку на астероид .
#Biography #Birth_Date #Events #12февраля
Чарлз Ро́берт Да́рвин (англ. Charles Robert Darwin, английское произношение: [tʃɑːlz 'dɑːwɪn]; 12 февраля 1809, Шрусбери, Шропшир — 19 апреля 1882, Даун Хаус[вд]) — английский биолог-эволюционист, зоолог, ботаник, палеонтолог, геолог; натуралист и путешественник; Одним из первых пришёл к выводу и обосновал идею о том, что все виды живых организмов эволюционируют со временем и происходят от общих предков. Развёрнутое изложение теории было опубликовано в 1859 году в книге «Происхождение видов».
Рэймонд Курцвейл (англ. Raymond Kurzweil; род. 12 февраля 1948, Нью-Йорк, США) — американский изобретатель и футуролог. Создатель многочисленных систем для распознавания речи. Известен научными технологическими прогнозами, учитывающими появление искусственного интеллекта и средств радикального продления жизни людей. Согласно Курцвейлу, в будущем человечество достигнет почти неограниченного материального изобилия, а люди могут стать бессмертными. Он также дал обоснование технологической сингулярности — феноменально быстрого научно-технического прогресса, основанного на мощном искусственном интеллекте (превосходящем человеческий) и киборгизации людей.
Эмилий Христианович Ленц (при рождении Генрих Фридрих Эмиль Ленц, нем. Heinrich Friedrich Emil Lenz; 12 (24) февраля 1804, Дерпт — 29 января (10 февраля) 1865, Рим) — российский физик немецкого происхождения; является одним из основоположников электротехники. С его именем связано открытие закона, определяющего тепловые действия тока, и закона, определяющего направление индукционного тока.
1961 — в Советском Союзе в сторону планеты Венера запущена автоматическая межпланетная станция «Венера-1». «Венера-1» стала первым космическим аппаратом, пролетевшим на близком расстоянии от планеты Венера.
2001 – космический аппарат NEAR Shoemaker совершил посадку в «седловидной» области астероида 433 Эрос , став первым космическим аппаратом, совершившим посадку на астероид .
#Biography #Birth_Date #Events #12февраля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Раздел 8. Stream API и функциональный стиль в Java
Глава 2: Анатомия Stream API. Ленивость и стоимость операций
Stream — это не данные, это план
Самая опасная ошибка при работе со Stream API — мыслить поток как контейнер данных, подобно коллекции. Эта иллюзия подкрепляется синтаксисом: мы вызываем методы на объекте stream, как будто он содержит элементы, готовые к выдаче. Но объект Stream — это не хранилище. Это абстрактное описание вычислительного процесса, чертёж без воплощения.
Чтобы разрушить эту иллюзию, рассмотрим простой эксперимент:
Между созданием потока и терминальной операцией нет способа узнать, сколько элементов пройдёт через фильтр. Нет метода size(), нет get(), нет iterator() без потребления потока.
Источники: рождение плана
Каждый поток начинается с источника (source), и характер источника определяет, как данные будут поступать в конвейер. Различные фабричные методы создают разные реализации Spliterator — механизма, ответственного за доступ к данным и их разделение.
Коллекции как источник
Метод Collection.stream() возвращает поток, построенный на Spliterator, предоставляемом самой коллекцией. ArrayList создаёт ArrayListSpliterator, который знает о своём размере (SIZED), поддерживает произвольный доступ и эффективно разделяется для параллельной обработки. LinkedList создаёт другой Spliterator, не знающий размера заранее и разделяющийся менее эффективно — последовательный обход узлов нельзя разрезать пополам без прохода.
Характеристики Spliterator — это метаданные, влияющие на оптимизацию. SIZED позволяет предвыделить точный размер результата. ORDERED гарантирует сохранение порядка при параллельном выполнении. NONNULL обещает отсутствие null-элементов, позволяя пропустить проверки.
Массивы и примитивы
Arrays.stream() создаёт специализированные потоки для примитивов (IntStream, LongStream, DoubleStream) с собственными сплитераторами. Это критично для производительности: примитивные потоки избегают боксинга (упаковки примитивов в объекты-обёртки), работая с сырыми значениями в памяти.
#Java #для_новичков #beginner #stream_api #stream
Глава 2: Анатомия Stream API. Ленивость и стоимость операций
Stream — это не данные, это план
Самая опасная ошибка при работе со Stream API — мыслить поток как контейнер данных, подобно коллекции. Эта иллюзия подкрепляется синтаксисом: мы вызываем методы на объекте stream, как будто он содержит элементы, готовые к выдаче. Но объект Stream — это не хранилище. Это абстрактное описание вычислительного процесса, чертёж без воплощения.
Чтобы разрушить эту иллюзию, рассмотрим простой эксперимент:
Stream<Book> stream = library.getBooks().stream()
.filter(b -> b.year() > 1950);
System.out.println("Stream создан");
System.out.println("Количество элементов: ???"); // Как узнать? Нельзя.
Между созданием потока и терминальной операцией нет способа узнать, сколько элементов пройдёт через фильтр. Нет метода size(), нет get(), нет iterator() без потребления потока.
Источники: рождение плана
Каждый поток начинается с источника (source), и характер источника определяет, как данные будут поступать в конвейер. Различные фабричные методы создают разные реализации Spliterator — механизма, ответственного за доступ к данным и их разделение.
Коллекции как источник
Метод Collection.stream() возвращает поток, построенный на Spliterator, предоставляемом самой коллекцией. ArrayList создаёт ArrayListSpliterator, который знает о своём размере (SIZED), поддерживает произвольный доступ и эффективно разделяется для параллельной обработки. LinkedList создаёт другой Spliterator, не знающий размера заранее и разделяющийся менее эффективно — последовательный обход узлов нельзя разрезать пополам без прохода.
// ArrayList: SIZED, ORDERED, SUBSIZED — оптимальные характеристики
List<Book> arrayList = new ArrayList<>();
Stream<Book> stream1 = arrayList.stream();
// LinkedList: только ORDERED — менее информативный Spliterator
List<Book> linkedList = new LinkedList<>();
Stream<Book> stream2 = linkedList.stream();
Характеристики Spliterator — это метаданные, влияющие на оптимизацию. SIZED позволяет предвыделить точный размер результата. ORDERED гарантирует сохранение порядка при параллельном выполнении. NONNULL обещает отсутствие null-элементов, позволяя пропустить проверки.
Массивы и примитивы
Arrays.stream() создаёт специализированные потоки для примитивов (IntStream, LongStream, DoubleStream) с собственными сплитераторами. Это критично для производительности: примитивные потоки избегают боксинга (упаковки примитивов в объекты-обёртки), работая с сырыми значениями в памяти.
// Без боксинга — прямая работа с int[]
int[] years = {1950, 1961, 1984, 2001};
IntStream yearStream = Arrays.stream(years);
// С боксином — Stream<Integer>, менее эффективен
Stream<Integer> boxedStream = Arrays.stream(years).boxed();
#Java #для_новичков #beginner #stream_api #stream
👍6🔥1
Генераторы и бесконечные потоки
Stream.iterate() и Stream.generate() создают потоки без заранее определённого источника данных. Их Spliterator не знает размера (NON_SIZED) и не поддерживает разделение для параллелизма. Это потоки, порождающие данные на лету по заданной функции.
Здесь данные не существуют до момента запроса. Spliterator вызывает предоставленную функцию для каждого элемента, проталкиваемого через конвейер. Бесконечность требует осторожности: без limit() или другой short-circuit операции терминальная операция никогда не завершится.
Параллельные потоки и разделение
Метод parallelStream() или .parallel() на существующем потоке активирует механизм ForkJoinPool. Но параллелизм возможен только если Spliterator поддерживает trySplit(). Этот метод разделяет оставшуюся часть данных на две половины, позволяя обработать их в разных потоках.
Понимание характеристик источника необходимо для оптимизации. Параллельный поток от Stream.iterate не только не ускорится, но может замедлиться из-за накладных расходов на координацию потоков без реального разделения работы.
Конвейер: архитектура плана
Когда мы вызываем промежуточные операции, мы не обрабатываем данные. Мы строим структуру данных — двусвязный список объектов-операций, каждый из которых знает о своём предшественнике и преемнике.
Внутренняя иерархия классов Stream API использует паттерн "Цепочка обязанностей" (Chain of Responsibility), реализованный через наследование от AbstractPipeline. Каждая промежуточная операция создаёт экземпляр анонимного подкласса: StatelessOp для операций без состояния (filter, map), StatefulOp для операций с состоянием (sorted, distinct, limit).
Когда мы пишем:
Создаётся цепочка: Head (источник) → FilterOps → MapOps → SortedOps. Каждый узел хранит ссылку на лямбду-логику и флаги операции (оптимизационные подсказки для конвейера).
Флаги операций (opFlags) — битовая маска, описывающая свойства операции. IS_SIZED означает, что операция не меняет количество элементов. NOT_SORTED означает, что операция может нарушить порядок. Эти флаги комбинируются через побитовые операции, позволяя оптимизировать конвейер: если ни одна операция не требует сохранения порядка, параллельное выполнение может избежать синхронизации на упорядочивании.
Промежуточные операции ленивы не потому, что "так принято", а потому, что их реализация не запускает обработку. Метод filter возвращает новый объект Stream, чей метод opWrapSink (создание приёмника данных) будет вызван позже, при терминальной операции. До этого момента мы просто наращиваем связный список описаний.
#Java #для_новичков #beginner #stream_api #stream
Stream.iterate() и Stream.generate() создают потоки без заранее определённого источника данных. Их Spliterator не знает размера (NON_SIZED) и не поддерживает разделение для параллелизма. Это потоки, порождающие данные на лету по заданной функции.
// Бесконечная последовательность: 0, 1, 2, 3...
Stream<Integer> natural = Stream.iterate(0, n -> n + 1);
// Бесконечный поток случайных книг
Stream<Book> randomBooks = Stream.generate(() -> generateRandomBook());
Здесь данные не существуют до момента запроса. Spliterator вызывает предоставленную функцию для каждого элемента, проталкиваемого через конвейер. Бесконечность требует осторожности: без limit() или другой short-circuit операции терминальная операция никогда не завершится.
Параллельные потоки и разделение
Метод parallelStream() или .parallel() на существующем потоке активирует механизм ForkJoinPool. Но параллелизм возможен только если Spliterator поддерживает trySplit(). Этот метод разделяет оставшуюся часть данных на две половины, позволяя обработать их в разных потоках.
// Хорошо делится: ArrayList, массивы, IntStream.range
List<Book> books = new ArrayList<>();
books.parallelStream() // Эффективное распараллеливание
// Плохо делится: Stream.iterate, Stream.generate, BufferedReader.lines()
Stream.iterate(0, n -> n + 1).parallel() // Нет выигрыша, возможен проигрыш
Понимание характеристик источника необходимо для оптимизации. Параллельный поток от Stream.iterate не только не ускорится, но может замедлиться из-за накладных расходов на координацию потоков без реального разделения работы.
Конвейер: архитектура плана
Когда мы вызываем промежуточные операции, мы не обрабатываем данные. Мы строим структуру данных — двусвязный список объектов-операций, каждый из которых знает о своём предшественнике и преемнике.
Внутренняя иерархия классов Stream API использует паттерн "Цепочка обязанностей" (Chain of Responsibility), реализованный через наследование от AbstractPipeline. Каждая промежуточная операция создаёт экземпляр анонимного подкласса: StatelessOp для операций без состояния (filter, map), StatefulOp для операций с состоянием (sorted, distinct, limit).
// Упрощённая внутренняя структура (псевдокод на основе OpenJDK)
abstract class AbstractPipeline<E_IN, E_OUT, S extends BaseStream<E_OUT, S>>
extends PipelineHelper<E_OUT> implements BaseStream<E_OUT, S> {
private final AbstractPipeline<?, E_IN, ?> previousStage; // Ссылка назад
private AbstractPipeline<?, E_OUT, ?> nextStage; // Ссылка вперёд
private int depth; // Глубина в конвейере
// Каждая операция оборачивает предыдущую
protected AbstractPipeline(AbstractPipeline<?, E_IN, ?> previousStage, int opFlags) {
this.previousStage = previousStage;
this.depth = previousStage.depth + 1;
previousStage.nextStage = this;
}
}
Когда мы пишем:
stream.filter(...).map(...).sorted(...)
Создаётся цепочка: Head (источник) → FilterOps → MapOps → SortedOps. Каждый узел хранит ссылку на лямбду-логику и флаги операции (оптимизационные подсказки для конвейера).
Флаги операций (opFlags) — битовая маска, описывающая свойства операции. IS_SIZED означает, что операция не меняет количество элементов. NOT_SORTED означает, что операция может нарушить порядок. Эти флаги комбинируются через побитовые операции, позволяя оптимизировать конвейер: если ни одна операция не требует сохранения порядка, параллельное выполнение может избежать синхронизации на упорядочивании.
Промежуточные операции ленивы не потому, что "так принято", а потому, что их реализация не запускает обработку. Метод filter возвращает новый объект Stream, чей метод opWrapSink (создание приёмника данных) будет вызван позже, при терминальной операции. До этого момента мы просто наращиваем связный список описаний.
#Java #для_новичков #beginner #stream_api #stream
👍3
Терминальная операция
Терминальная операция — это точка фазового перехода. План превращается в действие.
Методы collect, forEach, reduce, findFirst, anyMatch и другие запускают механизм, который:
- Создаёт "приёмник" (Sink) для последней операции конвейера
- Оборачивает его приёмником предыдущей операции, и так далее до источника
- Запрашивает у Spliterator источника обход элементов
- Для каждого элемента вызывает цепочку приёмников, пропуская данные через весь конвейер
Sink (поглотитель) — интерфейс, реализующий паттерн "Посетитель" (Visitor) для потоковых элементов. Он определяет четыре метода: begin (начало обхода), accept (обработка элемента), end (завершение), cancellationRequested (проверка необходимости остановки).
Ключевое наблюдение: элементы не "текут" через конвейер как вода в трубе. Каждый элемент полностью обрабатывается всеми операциями до того, как берётся следующий. Это "вертикальное" выполнение противопоставлено "горизонтальному" (где сначала все элементы проходят filter, затем все проходят map). Вертикальность критична для short-circuit операций — она позволяет остановиться после нахождения первого подходящего элемента, не обрабатывая остальные.
Потребление и неповторимость
После выполнения терминальной операции поток считается израсходованным. Повторный вызов терминальной операции выбросит IllegalStateException. Это архитектурное ограничение, а не техническая необходимость: многие источники (коллекции) допускали бы повторное чтение, но семантика потока как одноразового итератора упрощает внутреннюю реализацию и предотвращает ошибки при работе с источниками, которые действительно одноразовы (например, поток строк из файла, где файловый дескриптор закрывается после прочтения).
Если нужно многократное использование, применяем Supplier<Stream>:
Материализация: когда план становится данными
Не все операции сохраняют ленивость до конца. Операции с состоянием (stateful) — sorted, distinct, limit в параллельном потоке — требуют буферизации элементов для выполнения своей функции. sorted должен увидеть все элементы, прежде чем выдать первый. distinct должен хранить множество уже виденных элементов.
Эти операции вынуждают конвейер к материализации — промежуточному созданию структуры данных в памяти. Это разрушает иллюзию бесконечного потока: если подать бесконечный поток в sorted, программа зависнет в ожидании последнего элемента.
Понимание различия между stateless и stateful операциями необходимо для предсказания производительности и избежания бесконечных циклов.
#Java #для_новичков #beginner #stream_api #stream
Терминальная операция — это точка фазового перехода. План превращается в действие.
Методы collect, forEach, reduce, findFirst, anyMatch и другие запускают механизм, который:
- Создаёт "приёмник" (Sink) для последней операции конвейера
- Оборачивает его приёмником предыдущей операции, и так далее до источника
- Запрашивает у Spliterator источника обход элементов
- Для каждого элемента вызывает цепочку приёмников, пропуская данные через весь конвейер
Sink (поглотитель) — интерфейс, реализующий паттерн "Посетитель" (Visitor) для потоковых элементов. Он определяет четыре метода: begin (начало обхода), accept (обработка элемента), end (завершение), cancellationRequested (проверка необходимости остановки).
// Упрощённая логика терминальной операции (псевдокод)
public void evaluateParallel(PipelineHelper<T> helper, Spliterator<S> spliterator) {
// Создаём приёмник для конечной операции (например, collecting)
Sink<T> sink = makeSink();
// Оборачиваем в приёмники промежуточных операций, идя от хвоста к голове
for (AbstractPipeline p = lastStage; p != null; p = p.previousStage) {
sink = p.opWrapSink(sink);
}
// Запускаем обход источника
spliterator.forEachRemaining(sink::accept);
}
Ключевое наблюдение: элементы не "текут" через конвейер как вода в трубе. Каждый элемент полностью обрабатывается всеми операциями до того, как берётся следующий. Это "вертикальное" выполнение противопоставлено "горизонтальному" (где сначала все элементы проходят filter, затем все проходят map). Вертикальность критична для short-circuit операций — она позволяет остановиться после нахождения первого подходящего элемента, не обрабатывая остальные.
Потребление и неповторимость
После выполнения терминальной операции поток считается израсходованным. Повторный вызов терминальной операции выбросит IllegalStateException. Это архитектурное ограничение, а не техническая необходимость: многие источники (коллекции) допускали бы повторное чтение, но семантика потока как одноразового итератора упрощает внутреннюю реализацию и предотвращает ошибки при работе с источниками, которые действительно одноразовы (например, поток строк из файла, где файловый дескриптор закрывается после прочтения).
Stream<Book> stream = books.stream();
List<Book> first = stream.collect(toList()); // OK
List<Book> second = stream.collect(toList()); // IllegalStateException: stream has already been operated upon or closed
Если нужно многократное использование, применяем Supplier<Stream>:
Supplier<Stream<Book>> streamSupplier = () -> books.stream();
List<Book> first = streamSupplier.get().collect(toList());
List<Book> second = streamSupplier.get().filter(Book::isAvailable).collect(toList());
Материализация: когда план становится данными
Не все операции сохраняют ленивость до конца. Операции с состоянием (stateful) — sorted, distinct, limit в параллельном потоке — требуют буферизации элементов для выполнения своей функции. sorted должен увидеть все элементы, прежде чем выдать первый. distinct должен хранить множество уже виденных элементов.
Эти операции вынуждают конвейер к материализации — промежуточному созданию структуры данных в памяти. Это разрушает иллюзию бесконечного потока: если подать бесконечный поток в sorted, программа зависнет в ожидании последнего элемента.
Stream.iterate(0, n -> n + 1)
.sorted() // Опасность: попытка отсортировать бесконечность
.findFirst(); // Никогда не выполнится
Понимание различия между stateless и stateful операциями необходимо для предсказания производительности и избежания бесконечных циклов.
#Java #для_новичков #beginner #stream_api #stream
👍4
Что выведет код?
#Tasks
import java.util.Arrays;
import java.util.stream.Stream;
public class Task120226 {
public static void main(String[] args) {
String[] array = {"a", "b", "c"};
Stream<String> s1 = Arrays.stream(array);
Stream<String> s2 = Stream.of(array);
array[1] = "X";
System.out.println(s1.findFirst().orElse(""));
System.out.println(s2.skip(1).findFirst().orElse(""));
}
}
#Tasks
👍3🔥1
👍2
Что такое Deadlock, Livelock, Starvation? 🤓
Ответ:
Deadlock (взаимная блокировка) — ситуация, когда два или более потока бесконечно ждут друг друга, удерживая нужные им ресурсы (мониторы).
Livelock (активная блокировка) — потоки не блокируются, но постоянно меняют свое состояние в ответ на действия друг друга, не продвигаясь в работе (например, вежливо уступая дорогу).
Starvation (голодание) — поток не может получить доступ к общему ресурсу, потому что его постоянно перехватывают другие, более приоритетные потоки.
Deadlock предотвращают, упорядочивая захватов.
#собеседование
Ответ:
Deadlock (взаимная блокировка)
Livelock (активная блокировка) — потоки не блокируются, но постоянно меняют свое состояние в ответ на действия друг друга, не продвигаясь в работе (например, вежливо уступая дорогу).
Starvation (голодание) — поток не может получить доступ к общему ресурсу, потому что его постоянно перехватывают другие, более приоритетные потоки.
Deadlock предотвращают, упорядочивая захватов.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
История IT-технологий сегодня — 13 Февраля
ℹ️ Кто родился в этот день
Уи́льям Брэ́дфорд Шо́кли (англ. William Bradford Shockley; 13 февраля 1910, Лондон — 12 августа 1989, Станфорд) — американский физик, исследователь полупроводников, лауреат Нобелевской премии по физике 1956 года. В годы Второй мировой войны Шокли участвовал в создании американской школы исследования операций и в разработке тактики стратегических бомбардировок. В январе 1948 года Шокли изобрёл плоскостной биполярный транзистор, а затем создал научную теорию, объяснявшую его работу. В 1956 году Шокли основал названную его именем лабораторию, которая стала одним из истоков Кремниевой долины.
🌐 Знаковые события
1946 — американские военные объявили о создании первого цифрового компьютера Мокли и Экерта (ЭНИАК). Он потреблял 160 киловатт, имел 17 468 ламп, около 70 000 резисторов, 10 000 конденсаторов, 1500 реле и 6000 ручных переключателей.
2009 — Unix‑время достигает 1 234 567 890 секунд (03:31:30 UTC 13 февраля 2009)
#Biography #Birth_Date #Events #13февраля
Уи́льям Брэ́дфорд Шо́кли (англ. William Bradford Shockley; 13 февраля 1910, Лондон — 12 августа 1989, Станфорд) — американский физик, исследователь полупроводников, лауреат Нобелевской премии по физике 1956 года. В годы Второй мировой войны Шокли участвовал в создании американской школы исследования операций и в разработке тактики стратегических бомбардировок. В январе 1948 года Шокли изобрёл плоскостной биполярный транзистор, а затем создал научную теорию, объяснявшую его работу. В 1956 году Шокли основал названную его именем лабораторию, которая стала одним из истоков Кремниевой долины.
1946 — американские военные объявили о создании первого цифрового компьютера Мокли и Экерта (ЭНИАК). Он потреблял 160 киловатт, имел 17 468 ламп, около 70 000 резисторов, 10 000 конденсаторов, 1500 реле и 6000 ручных переключателей.
2009 — Unix‑время достигает 1 234 567 890 секунд (03:31:30 UTC 13 февраля 2009)
#Biography #Birth_Date #Events #13февраля
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3👍2
[Совет по Java #005]
Тема: Закрывайте ресурсы (InputStream, Connection, Scanner) в блоке try-with-resources. Это гарантирует их закрытие даже при исключении.
Проблема: Ручное управление ресурсами в блоке finally чревато ошибками и создает многословный, трудночитаемый код.
Разработчики часто забывают закрыть ресурс или делают это неправильно, пропуская проверку на null. Более того, если и при закрытии ресурса возникает исключение, оно может "проглотить" исходное исключение, произошедшее в блоке try. Это приводит к утечкам ресурсов (незакрытые файловые дескрипторы, соединения с БД, сетевые сокеты) и затрудняет диагностику корневых причин сбоев.
Даже корректно написанный finally блок не способен лаконично обработать несколько ресурсов, не прибегая к вложенным try-catch.
Решение: Начиная с Java 7, языковая конструкция try-with-resources обеспечивает автоматическое управление ресурсами.
Для использования ресурс должен реализовывать интерфейс-маркер java.lang.AutoCloseable (или его предшественник java.io.Closeable). Компилятор автоматически генерирует код, который закрывает ресурсы в порядке, обратном их объявлению, гарантируя вызов метода close() даже в случае исключения в блоке try. При этом все исключения, возникшие при закрытии, добавляются в подавленные (suppressed) исключения к основному исключению, что сохраняет полную картину ошибки.
Объяснение: Конструкция try (...) принимает одно или несколько объявлений ресурсов, разделенных точкой с запятой.
Каждый ресурс должен быть переменной инициализированного типа, реализующего AutoCloseable. Начиная с Java 9, допускается использование effectively final переменных, уже объявленных вне блока.
Компилятор транслирует try-with-resources в сложную последовательность try-catch-finally, корректно обрабатывающую иерархию исключений. Это не только сокращает объем кода, но и исключает самый распространенный класс ошибок, связанных с утечками системных ресурсов.
#Java #советы
Тема: Закрывайте ресурсы (InputStream, Connection, Scanner) в блоке try-with-resources. Это гарантирует их закрытие даже при исключении.
Проблема: Ручное управление ресурсами в блоке finally чревато ошибками и создает многословный, трудночитаемый код.
Разработчики часто забывают закрыть ресурс или делают это неправильно, пропуская проверку на null. Более того, если и при закрытии ресурса возникает исключение, оно может "проглотить" исходное исключение, произошедшее в блоке try. Это приводит к утечкам ресурсов (незакрытые файловые дескрипторы, соединения с БД, сетевые сокеты) и затрудняет диагностику корневых причин сбоев.
Даже корректно написанный finally блок не способен лаконично обработать несколько ресурсов, не прибегая к вложенным try-catch.
Решение: Начиная с Java 7, языковая конструкция try-with-resources обеспечивает автоматическое управление ресурсами.
Для использования ресурс должен реализовывать интерфейс-маркер java.lang.AutoCloseable (или его предшественник java.io.Closeable). Компилятор автоматически генерирует код, который закрывает ресурсы в порядке, обратном их объявлению, гарантируя вызов метода close() даже в случае исключения в блоке try. При этом все исключения, возникшие при закрытии, добавляются в подавленные (suppressed) исключения к основному исключению, что сохраняет полную картину ошибки.
import java.io.*;
import java.nio.file.*;
import java.sql.*;
public class ResourceManagement {
public static void main(String[] args) {
Path file = Paths.get("example.txt");
//Антипаттерн: Ручное закрытие с уязвимостями.
BufferedReader reader = null;
try {
reader = Files.newBufferedReader(file);
String line = reader.readLine();
System.out.println(line);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close(); // Дополнительный try-catch и риск потери исключения
} catch (IOException e) {
e.printStackTrace(); // Может затереть исходное исключение
}
}
}
//Решение: try-with-resources.
try (BufferedReader br = Files.newBufferedReader(file);
FileWriter fw = new FileWriter("output.txt")) { // Несколько ресурсов
String line = br.readLine();
fw.write(line);
} catch (IOException e) {
// Исключения из close() доступны через e.getSuppressed()
System.out.println("Основное исключение: " + e);
for (Throwable suppressed : e.getSuppressed()) {
System.out.println("Подавленное: " + suppressed);
}
}
// Пример с JDBC: ресурсы должны быть объявлены в правильном порядке.
String url = "jdbc:h2:mem:test";
String sql = "SELECT * FROM users";
try (Connection conn = DriverManager.getConnection(url);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
// Обработка результата
}
} catch (SQLException e) {
// Автоматическое закрытие Connection, Statement, ResultSet
}
}
}
Объяснение: Конструкция try (...) принимает одно или несколько объявлений ресурсов, разделенных точкой с запятой.
Каждый ресурс должен быть переменной инициализированного типа, реализующего AutoCloseable. Начиная с Java 9, допускается использование effectively final переменных, уже объявленных вне блока.
Компилятор транслирует try-with-resources в сложную последовательность try-catch-finally, корректно обрабатывающую иерархию исключений. Это не только сокращает объем кода, но и исключает самый распространенный класс ошибок, связанных с утечками системных ресурсов.
#Java #советы
👍3