Что такое массив (array) и как с ним работать? 🤓
Ответ:
Массив — это структура данных, которая хранит фиксированное количество элементов одного типа.
Доступ к элементам осуществляется по индексу (начиная с 0).
Массивы в Java являются объектами. Длина массива задается при создании и не может быть изменена. Массивы могут быть одномерными и многомерными. Для работы с массивами есть удобный класс Arrays с методами: sort(), binarySearch(), toString(), equals(), fill().
При создании массива все элементы получают значения по умолчанию (0, false, null).
#собеседование
Ответ:
Доступ к элементам осуществляется по индексу (начиная с 0).
Массивы в Java являются объектами. Длина массива задается при создании и не может быть изменена. Массивы могут быть одномерными и многомерными. Для работы с массивами есть удобный класс Arrays с методами: sort(), binarySearch(), toString(), equals(), fill().
При создании массива все элементы получают значения по умолчанию (0, false, null).
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
История IT-технологий сегодня — 19 Февраля
ℹ️ Кто родился в этот день
Никола́й Копе́рник (пол. Mikołaj Kopernik, нем. Niklas Koppernigk[5]; 19 февраля 1473, Торунь — 24 мая 1543, Фромборк) — польский и немецкий астроном, математик, механик, экономист, каноник эпохи Возрождения. Наиболее известен как автор гелиоцентрической системы мира, положившей начало первой научной революции.
🌐 Знаковые события
1946 — доклад Алана Тьюринга об ACE. На заседании исполнительного комитета Национальной физической лаборатории (NPL) представил первый детальный дизайн хранимо-программного компьютера ACE (Automatic Computing Engine). Это был первый проект компьютера с хранимой программой, вдохновлённый идеей машины Тьюринга; ACE стал важным шагом к архитектуре фон Неймана и стал прототипом для многих последующих систем.
#Biography #Birth_Date #Events #19февраля
Никола́й Копе́рник (пол. Mikołaj Kopernik, нем. Niklas Koppernigk[5]; 19 февраля 1473, Торунь — 24 мая 1543, Фромборк) — польский и немецкий астроном, математик, механик, экономист, каноник эпохи Возрождения. Наиболее известен как автор гелиоцентрической системы мира, положившей начало первой научной революции.
1946 — доклад Алана Тьюринга об ACE. На заседании исполнительного комитета Национальной физической лаборатории (NPL) представил первый детальный дизайн хранимо-программного компьютера ACE (Automatic Computing Engine). Это был первый проект компьютера с хранимой программой, вдохновлённый идеей машины Тьюринга; ACE стал важным шагом к архитектуре фон Неймана и стал прототипом для многих последующих систем.
#Biography #Birth_Date #Events #19февраля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
[Совет по Java #007]
Тема: System.currentTimeMillis() для замеров производительности ненадежен. Всегда используйте System.nanoTime().
Проблема: Использование System.currentTimeMillis() для измерения времени выполнения участков кода (профилирования, бенчмаркинга) является распространенной, но методологически неверной практикой.
Этот метод возвращает текущее время в миллисекундах, отсчитываемое от эпохи Unix (1 января 1970 года). Он подвержен влиянию корректировок системного времени, как ручных, так и автоматических (например, синхронизация через NTP — Network Time Protocol). Если во время замера системные часы будут переведены назад, результат может оказаться отрицательным, а если вперед — существенно завышенным. Кроме того, точности в миллисекундах может не хватать для измерения очень быстрых операций, длительность которых составляет микросекунды или наносекунды.
Решение: Для измерения интервалов времени предназначен метод System.nanoTime(). Он использует высокоточный таймер (high-resolution timer) с наносекундной точностью, если это поддерживается платформой. Важно понимать, что nanoTime() измеряет относительное время — некоторый произвольный, но фиксированный момент в прошлом (например, момент загрузки JVM).
Его нельзя использовать для получения текущего времени суток, но он идеально подходит для вычисления разницы (дельты) между двумя событиями. Метод не подвержен корректировкам системных часов и монотонно увеличивается, гарантируя корректность измерения промежутков времени.
#Java #советы
Тема: System.currentTimeMillis() для замеров производительности ненадежен. Всегда используйте System.nanoTime().
Проблема: Использование System.currentTimeMillis() для измерения времени выполнения участков кода (профилирования, бенчмаркинга) является распространенной, но методологически неверной практикой.
Этот метод возвращает текущее время в миллисекундах, отсчитываемое от эпохи Unix (1 января 1970 года). Он подвержен влиянию корректировок системного времени, как ручных, так и автоматических (например, синхронизация через NTP — Network Time Protocol). Если во время замера системные часы будут переведены назад, результат может оказаться отрицательным, а если вперед — существенно завышенным. Кроме того, точности в миллисекундах может не хватать для измерения очень быстрых операций, длительность которых составляет микросекунды или наносекунды.
Решение: Для измерения интервалов времени предназначен метод System.nanoTime(). Он использует высокоточный таймер (high-resolution timer) с наносекундной точностью, если это поддерживается платформой. Важно понимать, что nanoTime() измеряет относительное время — некоторый произвольный, но фиксированный момент в прошлом (например, момент загрузки JVM).
Его нельзя использовать для получения текущего времени суток, но он идеально подходит для вычисления разницы (дельты) между двумя событиями. Метод не подвержен корректировкам системных часов и монотонно увеличивается, гарантируя корректность измерения промежутков времени.
import java.util.concurrent.TimeUnit;
public class PerformanceMeasurement {
public static void main(String[] args) throws InterruptedException {
//Антипаттерн: Измерение через currentTimeMillis()
long startMillis = System.currentTimeMillis();
// Имитация работы
Thread.sleep(100);
long endMillis = System.currentTimeMillis();
long durationMillis = endMillis - startMillis;
System.out.println("currentTimeMillis() duration: " + durationMillis + " ms");
// Проблема: если во время замера часы переведятся назад,
// duration может быть отрицательным или неточным.
//Решение: Измерение через nanoTime()
long startNanos = System.nanoTime();
// Имитация работы
Thread.sleep(100);
long endNanos = System.nanoTime();
long durationNanos = endNanos - startNanos;
// Конвертация в миллисекунды для читаемости
long durationMs = TimeUnit.NANOSECONDS.toMillis(durationNanos);
double preciseMs = durationNanos / 1_000_000.0;
System.out.println("nanoTime() duration: " + durationNanos + " ns");
System.out.println("nanoTime() duration (ms): " + durationMs + " ms");
System.out.println("nanoTime() duration (precise ms): " + preciseMs + " ms");
// Демонстрация для сверхбыстрых операций
long fastStart = System.nanoTime();
int sum = 0;
for (int i = 0; i < 1000; i++) {
sum += i;
}
long fastEnd = System.nanoTime();
System.out.println("Loop duration: " + (fastEnd - fastStart) + " ns");
// Важно: nanoTime() нельзя использовать для получения времени суток
// System.out.println(System.nanoTime()); // Бессмысленное огромное число
}
// Правильный способ измерения среднего времени выполнения
public static double measureAverageTime(Runnable task, int iterations) {
// Прогрев JVM (warm-up) для компиляции и оптимизации кода
for (int i = 0; i < 10_000; i++) {
task.run();
}
long totalNanos = 0;
for (int i = 0; i < iterations; i++) {
long start = System.nanoTime();
task.run();
long end = System.nanoTime();
totalNanos += (end - start);
}
return (double) totalNanos / iterations;
}
}
#Java #советы
👍3🔥1
Объяснение: Метод System.nanoTime() использует наиболее точный таймер, доступный на платформе (например, TSC — Time Stamp Counter на процессорах x86).
Его точность и стабильность зависят от конкретной реализации JVM и операционной системы, но гарантированно не хуже, чем у currentTimeMillis(), а обычно на несколько порядков выше. Важно отметить, что на некоторых системах (например, виртуальные машины) nanoTime() может использовать тот же таймер, что и currentTimeMillis(), но без корректировок системного времени. При проведении микро-бенчмарков необходимо также учитывать необходимость прогрева JVM (как показано в методе measureAverageTime), чтобы код был скомпилирован JIT-компилятором, и результаты отражали реальную производительность, а не работу в режиме интерпретации.
Для серьезного бенчмаркинга следует использовать специализированные фреймворки, такие как JMH (Java Microbenchmark Harness), которые автоматически решают эти и многие другие проблемы.
#Java #советы
Его точность и стабильность зависят от конкретной реализации JVM и операционной системы, но гарантированно не хуже, чем у currentTimeMillis(), а обычно на несколько порядков выше. Важно отметить, что на некоторых системах (например, виртуальные машины) nanoTime() может использовать тот же таймер, что и currentTimeMillis(), но без корректировок системного времени. При проведении микро-бенчмарков необходимо также учитывать необходимость прогрева JVM (как показано в методе measureAverageTime), чтобы код был скомпилирован JIT-компилятором, и результаты отражали реальную производительность, а не работу в режиме интерпретации.
Для серьезного бенчмаркинга следует использовать специализированные фреймворки, такие как JMH (Java Microbenchmark Harness), которые автоматически решают эти и многие другие проблемы.
#Java #советы
👍3 3
Что выведет код?
#Tasks
package oleborn.taskswithspring.tasks.year2026;
public class Task190226 {
public static void main(String[] args) throws InterruptedException {
long start = System.currentTimeMillis();
Thread.sleep(5);
long end = System.currentTimeMillis();
long startNano = System.nanoTime();
Thread.sleep(5);
long endNano = System.nanoTime();
System.out.println("Millis diff: " + (end - start));
System.out.println("Nanos diff in ms: " + (endNano - startNano) / 1_000_000);
}
}
#Tasks
👍2
Что такое switch и как он работает? 🤓
Ответ:
switch — это условный оператор, который позволяет выбирать один из нескольких блоков кода для выполнения.
Он работает с типами: byte, short, char, int, их обертками, enum, String (начиная с Java 7). Оператор сравнивает значение выражения со значениями в case. При совпадении выполняется соответствующий блок до оператора break (если break нет, выполнение проваливается в следующий case — это называется fall-through).
Начиная с Java 12, появился более лаконичный switch-выражение с -> и yield.
#собеседование
Ответ:
Он работает с типами: byte, short, char, int, их обертками, enum, String (начиная с Java 7). Оператор сравнивает значение выражения со значениями в case. При совпадении выполняется соответствующий блок до оператора break (если break нет, выполнение проваливается в следующий case — это называется fall-through).
Начиная с Java 12, появился более лаконичный switch-выражение с -> и yield.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
История IT-технологий сегодня — 20 Февраля
ℹ️ Кто родился в этот день
Лю́двиг Бо́льцман (нем. Ludwig Eduard Boltzmann; 20 февраля 1844, Вена — 5 сентября 1906, Дуино, Цислейтания) — австрийский физик-теоретик, основатель статистической механики и молекулярно-кинетической теории. Его работы по статистической механике и энтропии напрямую предвосхитили формулу Шеннона для количества информации. Теория информации — математический фундамент сжатия данных, криптографии и передачи сигналов.
Джон Уи́ллард Ми́лнор (англ. John Willard Milnor; род. 20 февраля 1931, Ориндж[англ.], Нью-Джерси, США) — американский математик. Его работы по дифференциальной топологии и алгебраической топологии используются в компьютерной графике, геометрическом моделировании и теории сложных систем.
🌐 Знаковые события
1986 — выведен на орбиту базовый блок орбитальной станции «Мир».
#Biography #Birth_Date #Events #20февраля
Лю́двиг Бо́льцман (нем. Ludwig Eduard Boltzmann; 20 февраля 1844, Вена — 5 сентября 1906, Дуино, Цислейтания) — австрийский физик-теоретик, основатель статистической механики и молекулярно-кинетической теории. Его работы по статистической механике и энтропии напрямую предвосхитили формулу Шеннона для количества информации. Теория информации — математический фундамент сжатия данных, криптографии и передачи сигналов.
Джон Уи́ллард Ми́лнор (англ. John Willard Milnor; род. 20 февраля 1931, Ориндж[англ.], Нью-Джерси, США) — американский математик. Его работы по дифференциальной топологии и алгебраической топологии используются в компьютерной графике, геометрическом моделировании и теории сложных систем.
1986 — выведен на орбиту базовый блок орбитальной станции «Мир».
#Biography #Birth_Date #Events #20февраля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Раздел 8. Stream API и функциональный стиль в Java
Глава 3: Чистые преобразования и борьба с исключениями
filter, map, flatMap — кирпичи декларативности
Stream API предоставляет минимальный, но выразительный набор операций для декларативной обработки данных. Если императивный код строится из циклов, условий и временных переменных, то потоковый код компонуется из трёх фундаментальных примитивов: фильтрации, отображения и свёртки. Рассмотрим первые два и их мощное обобщение — flatMap.
filter: селекция по предикату
Операция filter принимает Predicate<T> — функцию, возвращающую boolean — и возвращает поток, содержащий только элементы, удовлетворяющие условию. Это декларативный аналог условного оператора в цикле, но без видимого управления состоянием.
Важно понимать, что filter — операция без состояния (stateless). Она не требует памяти, пропорциональной количеству элементов, и не изменяет порядок. Каждый элемент проверяется независимо, в изоляции от других. Это делает filter идеальным для распараллеливания: элементы можно проверять в любом порядке и в любых потоках без синхронизации.
Стоимость filter — O(1) на элемент плюс стоимость выполнения предиката. Предикат должен быть чистой функцией: детерминированной, без побочных эффектов, зависящей только от входного элемента.
Нарушение этого правила — распространённый источник багов:
При параллельном выполнении счётчик будет инкрементироваться из нескольких потоков без синхронизации, давая непредсказуемый результат.
#Java #для_новичков #beginner #stream_api #filter
Глава 3: Чистые преобразования и борьба с исключениями
filter, map, flatMap — кирпичи декларативности
Stream API предоставляет минимальный, но выразительный набор операций для декларативной обработки данных. Если императивный код строится из циклов, условий и временных переменных, то потоковый код компонуется из трёх фундаментальных примитивов: фильтрации, отображения и свёртки. Рассмотрим первые два и их мощное обобщение — flatMap.
filter: селекция по предикату
Операция filter принимает Predicate<T> — функцию, возвращающую boolean — и возвращает поток, содержащий только элементы, удовлетворяющие условию. Это декларативный аналог условного оператора в цикле, но без видимого управления состоянием.
Stream<Book> classics = library.stream()
.filter(book -> book.year() < 1980);
Важно понимать, что filter — операция без состояния (stateless). Она не требует памяти, пропорциональной количеству элементов, и не изменяет порядок. Каждый элемент проверяется независимо, в изоляции от других. Это делает filter идеальным для распараллеливания: элементы можно проверять в любом порядке и в любых потоках без синхронизации.
Стоимость filter — O(1) на элемент плюс стоимость выполнения предиката. Предикат должен быть чистой функцией: детерминированной, без побочных эффектов, зависящей только от входного элемента.
Нарушение этого правила — распространённый источник багов:
// Антипаттерн: предикат с побочным эффектом
AtomicInteger counter = new AtomicInteger(0);
Stream<Book> everyThird = library.stream()
.filter(b -> counter.incrementAndGet() % 3 == 0); // Недетерминировано при parallel()
При параллельном выполнении счётчик будет инкрементироваться из нескольких потоков без синхронизации, давая непредсказуемый результат.
#Java #для_новичков #beginner #stream_api #filter
👍4
map: структурная трансформация
Операция map принимает Function<T, R> и применяет её к каждому элементу, заменяя его результатом функции. Это преобразование типа: из потока книг делаем поток названий, из потока строк — поток их длин, из потока заказов — поток сумм.
map также stateless и ленив. Функция вызывается только при запросе элемента терминальной операцией. Стоимость — O(1) на элемент плюс стоимость функции. Функция должна быть чистой: один и тот же вход всегда даёт один и тот же выход, без модификации внешнего состояния.
Композиция map позволяет выстраивать цепочки преобразований, читаемые справа налево или через method reference:
Каждый map — отдельный узел конвейера, отдельный объект в памяти. Для простых преобразований это приемлемо, но для тяжёлых операций композиция нескольких map может быть менее эффективна, чем одно комплексное преобразование, из-за накладных расходов на вызовы лямбд и промежуточные объекты.
flatMap: разворачивание иерархий
flatMap — наиболее мощный и наиболее сложный из трёх примитивов. Он решает проблему, которую map решить не может: когда один элемент источника порождает ноль, один или множество элементов результата.
Сигнатура flatMap требует функцию, возвращающую Stream<R> вместо R. Операция применяет эту функцию к каждому элементу, получает потоки результатов и сливает их в единый выходной поток. Это аналог вложенных циклов или операции "расплющивания" (flattening) в функциональных языках.
Классический сценарий: коллекция внутри коллекции
Предположим, у нас есть список заказов, каждый содержит список позиций.
Нужно получить поток всех позиций всех заказов:
Здесь order -> order.getItems().stream() — функция, превращающая один Order в Stream<OrderItem>. flatMap выполняет слияние этих потоков, устраняя уровень вложенности. Результат — плоский поток всех элементов.
Нулевое и единичное отображение
flatMap универсален: он обрабатывает все случаи количества выходных элементов на входной:
Ноль элементов: возвращаем Stream.empty(), элемент исключается из результата
Один элемент: возвращаем Stream.of(element), эквивалентно map с последующим filter(Objects::nonNull)
Множество элементов: возвращаем collection.stream(), все элементы включаются в результат
#Java #для_новичков #beginner #stream_api #filter #flatMap #map
Операция map принимает Function<T, R> и применяет её к каждому элементу, заменяя его результатом функции. Это преобразование типа: из потока книг делаем поток названий, из потока строк — поток их длин, из потока заказов — поток сумм.
Stream<String> titles = library.stream()
.map(Book::title);
Stream<Integer> lengths = titles.map(String::length);
map также stateless и ленив. Функция вызывается только при запросе элемента терминальной операцией. Стоимость — O(1) на элемент плюс стоимость функции. Функция должна быть чистой: один и тот же вход всегда даёт один и тот же выход, без модификации внешнего состояния.
Композиция map позволяет выстраивать цепочки преобразований, читаемые справа налево или через method reference:
// Цепочка преобразований: Book -> String -> Integer -> String
String summary = book.stream()
.map(Book::author) // Book -> String
.map(String::toUpperCase) // String -> String
.map(author -> author.substring(0, 3)) // String -> String
.map(prefix -> "Author: " + prefix) // String -> String
.findFirst()
.orElse("Unknown");
Каждый map — отдельный узел конвейера, отдельный объект в памяти. Для простых преобразований это приемлемо, но для тяжёлых операций композиция нескольких map может быть менее эффективна, чем одно комплексное преобразование, из-за накладных расходов на вызовы лямбд и промежуточные объекты.
flatMap: разворачивание иерархий
flatMap — наиболее мощный и наиболее сложный из трёх примитивов. Он решает проблему, которую map решить не может: когда один элемент источника порождает ноль, один или множество элементов результата.
Сигнатура flatMap требует функцию, возвращающую Stream<R> вместо R. Операция применяет эту функцию к каждому элементу, получает потоки результатов и сливает их в единый выходной поток. Это аналог вложенных циклов или операции "расплющивания" (flattening) в функциональных языках.
Классический сценарий: коллекция внутри коллекции
Предположим, у нас есть список заказов, каждый содержит список позиций.
Нужно получить поток всех позиций всех заказов:
List<Order> orders = fetchOrders();
// Императивный подход: вложенные циклы, временная коллекция
List<OrderItem> allItems = new ArrayList<>();
for (Order order : orders) {
for (OrderItem item : order.getItems()) {
allItems.add(item);
}
}
// Декларативный подход: flatMap
Stream<OrderItem> itemStream = orders.stream()
.flatMap(order -> order.getItems().stream());
Здесь order -> order.getItems().stream() — функция, превращающая один Order в Stream<OrderItem>. flatMap выполняет слияние этих потоков, устраняя уровень вложенности. Результат — плоский поток всех элементов.
Нулевое и единичное отображение
flatMap универсален: он обрабатывает все случаи количества выходных элементов на входной:
Ноль элементов: возвращаем Stream.empty(), элемент исключается из результата
Один элемент: возвращаем Stream.of(element), эквивалентно map с последующим filter(Objects::nonNull)
Множество элементов: возвращаем collection.stream(), все элементы включаются в результат
// Фильтрация через flatMap: ноль или один элемент
Stream<Book> validBooks = rawData.stream()
.flatMap(data -> {
try {
Book book = parseBook(data); // Может бросить исключение
return Stream.of(book); // Один элемент при успехе
} catch (ParseException e) {
return Stream.empty(); // Ноль элементов при ошибке
}
});
#Java #для_новичков #beginner #stream_api #filter #flatMap #map
👍5
Сложность и читаемость
Мощь flatMap оборачивается риском чрезмерной сложности.
Вложенные flatMap создают "лестницу" преобразований, сложную для восприятия:
Этот код эквивалентен четырём вложенным циклам. Он работает, но его трудно читать и отлаживать. Каждый уровень вложенности добавляет лексический контекст, и переменные верхних уровней (order, shipment) доступны во вложенных лямбдах, создавая неявные зависимости.
Рефакторинг через промежуточные методы улучшает читаемость:
Или использование mapMulti (Java 16+) — операции, комбинирующей map и flatMap с более эффективной реализацией для множественного вывода:
mapMulti избегает создания промежуточных объектов Stream для каждого элемента, что снижает нагрузку на GC при глубокой вложенности.
Анализ стоимости
filter: O(1) на элемент. Память: O(1). Параллелизм: отличный, нет синхронизации.
map: O(1) на элемент плюс стоимость функции. Память: O(1) для примитивов, O(1) для ссылок (создаётся новый объект результата). Параллелизм: отличный.
flatMap: O(1) на элемент плюс стоимость создания выходного потока плюс стоимость его обхода. Память: зависит от размера выходных потоков. Параллелизм: сложный — слияние множественных потоков требует координации.
Скрытая стоимость flatMap — в аллокациях. Каждый вызов функции создаёт новый объект Stream (обычно через Collection.stream() или Stream.of()). Для больших коллекций это давит на Young Generation. Оптимизация через mapMulti или специализированные сплитераторы уместна в критичных секциях.
Композиция как язык запросов
Комбинация filter, map, flatMap образует внутренний DSL (domain-specific language) для преобразования данных.
Хорошо спроектированный конвейер читается как предложение на естественном языке:
Каждая операция — глагол, каждый метод reference или лямбда — дополнение. Порядок операций отражает логику обработки: сначала сужаем (filter), затем расплющиваем (flatMap), затем нормализуем (distinct, sorted).
#Java #для_новичков #beginner #stream_api #filter #flatMap #map
Мощь flatMap оборачивается риском чрезмерной сложности.
Вложенные flatMap создают "лестницу" преобразований, сложную для восприятия:
// Антипаттерн: глубокая вложенность flatMap
Stream<String> deepStream = orders.stream()
.flatMap(order -> order.getShipments().stream()
.flatMap(shipment -> shipment.getPackages().stream()
.flatMap(pkg -> pkg.getItems().stream()
.flatMap(item -> item.getTags().stream()))));
Этот код эквивалентен четырём вложенным циклам. Он работает, но его трудно читать и отлаживать. Каждый уровень вложенности добавляет лексический контекст, и переменные верхних уровней (order, shipment) доступны во вложенных лямбдах, создавая неявные зависимости.
Рефакторинг через промежуточные методы улучшает читаемость:
// Лучше: именованные методы с ясной семантикой
Stream<String> tags = orders.stream()
.flatMap(this::extractShipments)
.flatMap(this::extractPackages)
.flatMap(this::extractItems)
.flatMap(this::extractTags);
private Stream<Shipment> extractShipments(Order order) {
return order.getShipments().stream();
}
// ... и так далее
Или использование mapMulti (Java 16+) — операции, комбинирующей map и flatMap с более эффективной реализацией для множественного вывода:
// mapMulti: более эффективен, чем flatMap, для множественных элементов
Stream<String> tags = orders.stream()
.<String>mapMulti((order, consumer) -> {
for (Shipment s : order.getShipments()) {
for (Package p : s.getPackages()) {
for (Item i : p.getItems()) {
for (String tag : i.getTags()) {
consumer.accept(tag); // Прямая передача без создания Stream
}
}
}
}
});
mapMulti избегает создания промежуточных объектов Stream для каждого элемента, что снижает нагрузку на GC при глубокой вложенности.
Анализ стоимости
filter: O(1) на элемент. Память: O(1). Параллелизм: отличный, нет синхронизации.
map: O(1) на элемент плюс стоимость функции. Память: O(1) для примитивов, O(1) для ссылок (создаётся новый объект результата). Параллелизм: отличный.
flatMap: O(1) на элемент плюс стоимость создания выходного потока плюс стоимость его обхода. Память: зависит от размера выходных потоков. Параллелизм: сложный — слияние множественных потоков требует координации.
Скрытая стоимость flatMap — в аллокациях. Каждый вызов функции создаёт новый объект Stream (обычно через Collection.stream() или Stream.of()). Для больших коллекций это давит на Young Generation. Оптимизация через mapMulti или специализированные сплитераторы уместна в критичных секциях.
Композиция как язык запросов
Комбинация filter, map, flatMap образует внутренний DSL (domain-specific language) для преобразования данных.
Хорошо спроектированный конвейер читается как предложение на естественном языке:
// "Найти все уникальные теги из активных заказов, отсортированные по алфавиту"
List<String> sortedUniqueTags = orders.stream()
.filter(Order::isActive) // которые активны
.flatMap(o -> o.getTags().stream()) // извлечь все теги
.distinct() // уникальные
.sorted() // отсортированные
.collect(toList()); // собрать в список
Каждая операция — глагол, каждый метод reference или лямбда — дополнение. Порядок операций отражает логику обработки: сначала сужаем (filter), затем расплющиваем (flatMap), затем нормализуем (distinct, sorted).
#Java #для_новичков #beginner #stream_api #filter #flatMap #map
👍3
Что выведет код?
#Tasks
import java.util.stream.Stream;
public class Task200226 {
public static void main(String[] args) {
Stream.of(1, 2, 3, 4, 5)
.filter(i -> {
System.out.print(i + " ");
return i % 2 == 0;
})
.map(i -> i * 10)
.findFirst()
.ifPresent(i -> System.out.print("result: " + i));
}
}
#Tasks
👍2
Варианты ответа:
Anonymous Quiz
23%
2 result: 20
9%
1 2 result: 20
59%
1 2 3 4 5 result: 20
9%
result: 20
Чем отличается throw от throws? 🤓
Ответ:
Оба ключевых слова связаны с обработкой исключений, но выполняют разные функции.
throws используется в сигнатуре метода, чтобы объявить, что метод может выбросить указанные исключения (обычно проверяемые). Это предупреждение для вызывающего кода.
throw — это оператор, который фактически создает и выбрасывает объект исключения (например, throw new IOException("Ошибка")).
throw используется внутри тела метода.
#собеседование
Ответ:
throws используется в сигнатуре метода, чтобы объявить, что метод может выбросить указанные исключения (обычно проверяемые). Это предупреждение для вызывающего кода.
throw — это оператор, который фактически создает и выбрасывает объект исключения (например, throw new IOException("Ошибка")).
throw используется внутри тела метода.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
История технологий сегодня — 21 Февраля
ℹ️ Кто родился в этот день
Михаи́л Алекса́ндрович Бонч-Бруе́вич (9 (21) февраля 1888, Орёл — 7 марта 1940, Ленинград) — русский и советский радиотехник, основатель российской радиоламповой промышленности. Член-корреспондент АН СССР (1931). Профессор Московского высшего технического училища (1922), Ленинградского института инженеров связи (1932), доктор технических наук, один из основателей и руководителей Нижегородской радиолаборатории. Внёс значительный вклад в развитие советской радиофизики, разработку новых типов радиоламп, аппаратуры радиовещания и радиосвязи. Автор учебников, научных работ, а также около 60 патентов на изобретения в области радиотехники.
🌐 Знаковые события
2006 — космическим телескопом «Хаббл» открыт астрономический объект неизвестного типа SCP 06F6, природу которого астрономы не могут объяснить до сих пор.
#Biography #Birth_Date #Events #21февраля
Михаи́л Алекса́ндрович Бонч-Бруе́вич (9 (21) февраля 1888, Орёл — 7 марта 1940, Ленинград) — русский и советский радиотехник, основатель российской радиоламповой промышленности. Член-корреспондент АН СССР (1931). Профессор Московского высшего технического училища (1922), Ленинградского института инженеров связи (1932), доктор технических наук, один из основателей и руководителей Нижегородской радиолаборатории. Внёс значительный вклад в развитие советской радиофизики, разработку новых типов радиоламп, аппаратуры радиовещания и радиосвязи. Автор учебников, научных работ, а также около 60 патентов на изобретения в области радиотехники.
2006 — космическим телескопом «Хаббл» открыт астрономический объект неизвестного типа SCP 06F6, природу которого астрономы не могут объяснить до сих пор.
#Biography #Birth_Date #Events #21февраля
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
С 14.02 по 20.02
Предыдущий пост(с 07.02 по 13.02)
Воскресный мотивационный пост:
Не было мотивации
Запись встреч/видео:
6. От сырых метрик к production-мониторингу: Prometheus и Grafana
Обучающие статьи:
Раздел 8. Stream API и функциональный стиль
Глава 2: Анатомия Stream API. Ленивость и стоимость операций
Ленивость и Short-Circuit — ключ к эффективности
(Практика): Диссекция конвейера в «Библиотеке»
Глава 3: Чистые преобразования и борьба с исключениями
filter, map, flatMap — кирпичи декларативности
Советы по Java:
[Совет по Java #006]
Используйте Enum вместо строковых констант для ограниченного набора значений
[Совет по Java #007]
System.currentTimeMillis() для замеров производительности ненадежен. Всегда используйте System.nanoTime().
Полезные статьи и видео:
Hot reload секретов под нагрузкой в Java-сервисах на Spring
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
Предыдущий пост(с 07.02 по 13.02)
Воскресный мотивационный пост:
Не было мотивации
Запись встреч/видео:
6. От сырых метрик к production-мониторингу: Prometheus и Grafana
Обучающие статьи:
Раздел 8. Stream API и функциональный стиль
Глава 2: Анатомия Stream API. Ленивость и стоимость операций
Ленивость и Short-Circuit — ключ к эффективности
(Практика): Диссекция конвейера в «Библиотеке»
Глава 3: Чистые преобразования и борьба с исключениями
filter, map, flatMap — кирпичи декларативности
Советы по Java:
[Совет по Java #006]
Используйте Enum вместо строковых констант для ограниченного набора значений
[Совет по Java #007]
System.currentTimeMillis() для замеров производительности ненадежен. Всегда используйте System.nanoTime().
Полезные статьи и видео:
Hot reload секретов под нагрузкой в Java-сервисах на Spring
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
👍3🔥2 2
А давайте сегодня, часиков в 17 по мск встретимся и поболтаем? ☺️
Что-то давно Вас всех не видел)))
Расскажете как у вас дела😉
Придете?📞
Что-то давно Вас всех не видел)))
Расскажете как у вас дела
Придете?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
История технологий сегодня — 22 Февраля
ℹ️ Кто родился в этот день
Томас Курц (англ. Thomas Eugene Kurtz; 22 февраля 1928, Ок-Парк — 12 ноября 2024, Лебанон[англ.]) — американский учёный в области информатики, один из разработчиков языка программирования Бейсик. В начале — середине 1960-х годов совместно с Джоном Кемени разработал Бейсик и DTTS (англ. Dartmouth Time Sharing System) — операционную систему для PDP-1, отмечаемую как первую успешную крупномасштабную реализацию концепции разделения времени.
Ирвинг «Эл» Гросс (/ɡroʊs/; 22 февраля 1918 — 21 декабря 2000) — был пионером мобильной беспроводной связи. Он создал и запатентовал множество коммуникационных устройств, в частности, раннюю версию рации, радиостанции гражданского диапазона, пейджер и беспроводной телефон.
🌐 Знаковые события
1966 — запущен спутник «Космос-110» с собаками Ветерком и Угольком на борту.
#Biography #Birth_Date #Events #22февраля
Томас Курц (англ. Thomas Eugene Kurtz; 22 февраля 1928, Ок-Парк — 12 ноября 2024, Лебанон[англ.]) — американский учёный в области информатики, один из разработчиков языка программирования Бейсик. В начале — середине 1960-х годов совместно с Джоном Кемени разработал Бейсик и DTTS (англ. Dartmouth Time Sharing System) — операционную систему для PDP-1, отмечаемую как первую успешную крупномасштабную реализацию концепции разделения времени.
Ирвинг «Эл» Гросс (/ɡroʊs/; 22 февраля 1918 — 21 декабря 2000) — был пионером мобильной беспроводной связи. Он создал и запатентовал множество коммуникационных устройств, в частности, раннюю версию рации, радиостанции гражданского диапазона, пейджер и беспроводной телефон.
1966 — запущен спутник «Космос-110» с собаками Ветерком и Угольком на борту.
#Biography #Birth_Date #Events #22февраля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
ГЛОБАЛИЗАЦИЯ ЗАКАНЧИВАЕТСЯ
Помните эту картинку, нарисованную влажной рекламой?
Айтишник на лежаке у океана. В одной руке — «Пина колада». А другой — пуш в гит. Проект в России. Жизнь в Таиланде. Зарплата в долларах.
Многие пошли в айти из-за этого. Многие сорвались в далёкие страны за убегающей картинкой-мечтой.
И да, некоторые добились желаемого.
Но мне всегда хотелось понять: ценой чего?
Жить там, где тебя терпят, пока есть деньги?
Бросить родных, друзей, свой двор — чтобы пожить красиво?
Быть вечным чужим и никогда не почувствовать, что ты на своей земле?
ЭТО НЕ КРИЗИС. ЭТО ЗАКАТ ГЛОБАЛИЗАЦИИ.
Если вы следите за миром, вы уже видели: торговые войны, санкции, запреты на чипы и облака, требования локализовать данные. Каждая страна строит свои цифровые стены.
Но многие всё ещё думают: потерпим, переждём, все вернётся к прежнему и привычному.
Нифига ребят.
Санкционные режимы — не временные проблемы. Это новые правила. Тем более в России, где большинство из нас родилось и живет. И даже в соседних странах, которые подмахивают в сторону запада - ничего не останется прежним.
Ограничения на полупроводники, ИИ, облака — долгосрочная политика ведущих держав. Данные больше не текут свободно — они стали стратегическим ресурсом, как нефть или уран.
И речь не о паре проблемных лет. Речь о том, что мир перестраивается навсегда.
IT ВНЕ ПОЛИТИКИ? ЗАБУДЬТЕ.
Раньше можно было прятаться за мантру: код — вне политики. GitHub — глобален. Мы — граждане интернета.
Как же сейчас это звучит смешно. Китай и США, Россия и Европейский союз - полностью расходятся бортами.
Код — теперь инфраструктура государства. Облака — суверенитет. Чипы — оборона. Разработчик больше не "фрилансер". Он встроен в геоэкономическую систему конкретной страны.
И выбраться из этого нельзя — можно только осознать и принять или начать бороться с ветряной мельницей.
Вы думаете, вас не коснётся? Посмотрите на карту, компании разделяются на региональные экосистемы. Доступы к сервисам обрываются.
Вчерашние «глобальные» инструменты завтра потребуют лицензию, которой у вас нет и не будет потому что цифровая стена отгородила Вас.
ПОЧЕМУ ЭТО ПРОИСХОДИТ ИМЕННО СЕЙЧАС?
Раньше границы были физическими. Теперь они стали цифровыми. И конфликты уходят туда же — в кремний, в протоколы, в исходный код. Борьба идёт не за территории, а за данные и контроль над ними.
Кто первым станет владеть цифрой - будет у руля будущего.
Поэтому сейчас вкладывают триллионы в ИИ, в надежде, что он решит все проблемы своих создателей.
Поэтому мир меняется. И не только в нашей стране.
ЧТО ЭТО ЗНАЧИТ ДЛЯ НАС?
Мир меняется. И вместе с ним меняются правила игры.
Раньше наши ребята писали код для стартапов из Кремниевой долины, делали фичи для европейских финтех-проектов, грезили офферами в FAANG. И успех измерялся тем, как далеко они уехали от дома.
Это была эпоха потребителей глобализации.
Теперь наступает эпоха строителей.
Посмотрите на карту: огромные рынки — Россия, Китай, Иран, многие страны Африки и Латинской Америки — выпадают из западной цифровой орбиты. Но люди там не перестали пользоваться приложениями, не перестали платить, не перестали общаться.
Кто закроет эти потребности?
Вспомните историю: когда Америка ввела эмбарго на технологии для СССР, мы не перестали летать в космос. Мы построили свою космонавтику.
Сейчас перед нами стоит точно такая же задача: построить свой цифровой мир. Не догоняющий и не копирующий, а свой.
Да, это сложно. Да, придется переучиваться. Придется забыть про "просто вставить готовую библиотеку с гитхаба" — потому что завтра её могут отозвать. Да и гитхаб заблокировать для пользователей "недружественной страны".
Придется научиться делать глубокие, безопасные, суверенные продукты с нуля.
И да, нас ждут горы ошибок и тонны недальновидных, "топорных" решений. Но без этого, в мире гигантов мы останемся карликами.
Глобализация заканчивается. Начинается эра мастеров. И она уже идёт, прямо здесь и сейчас.
😎 @Oleborn
Помните эту картинку, нарисованную влажной рекламой?
Айтишник на лежаке у океана. В одной руке — «Пина колада». А другой — пуш в гит. Проект в России. Жизнь в Таиланде. Зарплата в долларах.
Многие пошли в айти из-за этого. Многие сорвались в далёкие страны за убегающей картинкой-мечтой.
И да, некоторые добились желаемого.
Но мне всегда хотелось понять: ценой чего?
Жить там, где тебя терпят, пока есть деньги?
Бросить родных, друзей, свой двор — чтобы пожить красиво?
Быть вечным чужим и никогда не почувствовать, что ты на своей земле?
ЭТО НЕ КРИЗИС. ЭТО ЗАКАТ ГЛОБАЛИЗАЦИИ.
Если вы следите за миром, вы уже видели: торговые войны, санкции, запреты на чипы и облака, требования локализовать данные. Каждая страна строит свои цифровые стены.
Но многие всё ещё думают: потерпим, переждём, все вернётся к прежнему и привычному.
Нифига ребят.
Санкционные режимы — не временные проблемы. Это новые правила. Тем более в России, где большинство из нас родилось и живет. И даже в соседних странах, которые подмахивают в сторону запада - ничего не останется прежним.
Ограничения на полупроводники, ИИ, облака — долгосрочная политика ведущих держав. Данные больше не текут свободно — они стали стратегическим ресурсом, как нефть или уран.
И речь не о паре проблемных лет. Речь о том, что мир перестраивается навсегда.
IT ВНЕ ПОЛИТИКИ? ЗАБУДЬТЕ.
Раньше можно было прятаться за мантру: код — вне политики. GitHub — глобален. Мы — граждане интернета.
Как же сейчас это звучит смешно. Китай и США, Россия и Европейский союз - полностью расходятся бортами.
Код — теперь инфраструктура государства. Облака — суверенитет. Чипы — оборона. Разработчик больше не "фрилансер". Он встроен в геоэкономическую систему конкретной страны.
И выбраться из этого нельзя — можно только осознать и принять или начать бороться с ветряной мельницей.
Вы думаете, вас не коснётся? Посмотрите на карту, компании разделяются на региональные экосистемы. Доступы к сервисам обрываются.
Вчерашние «глобальные» инструменты завтра потребуют лицензию, которой у вас нет и не будет потому что цифровая стена отгородила Вас.
ПОЧЕМУ ЭТО ПРОИСХОДИТ ИМЕННО СЕЙЧАС?
Раньше границы были физическими. Теперь они стали цифровыми. И конфликты уходят туда же — в кремний, в протоколы, в исходный код. Борьба идёт не за территории, а за данные и контроль над ними.
Кто первым станет владеть цифрой - будет у руля будущего.
Поэтому сейчас вкладывают триллионы в ИИ, в надежде, что он решит все проблемы своих создателей.
Поэтому мир меняется. И не только в нашей стране.
ЧТО ЭТО ЗНАЧИТ ДЛЯ НАС?
Мир меняется. И вместе с ним меняются правила игры.
Раньше наши ребята писали код для стартапов из Кремниевой долины, делали фичи для европейских финтех-проектов, грезили офферами в FAANG. И успех измерялся тем, как далеко они уехали от дома.
Это была эпоха потребителей глобализации.
Теперь наступает эпоха строителей.
Посмотрите на карту: огромные рынки — Россия, Китай, Иран, многие страны Африки и Латинской Америки — выпадают из западной цифровой орбиты. Но люди там не перестали пользоваться приложениями, не перестали платить, не перестали общаться.
Кто закроет эти потребности?
Вспомните историю: когда Америка ввела эмбарго на технологии для СССР, мы не перестали летать в космос. Мы построили свою космонавтику.
Сейчас перед нами стоит точно такая же задача: построить свой цифровой мир. Не догоняющий и не копирующий, а свой.
Да, это сложно. Да, придется переучиваться. Придется забыть про "просто вставить готовую библиотеку с гитхаба" — потому что завтра её могут отозвать. Да и гитхаб заблокировать для пользователей "недружественной страны".
Придется научиться делать глубокие, безопасные, суверенные продукты с нуля.
И да, нас ждут горы ошибок и тонны недальновидных, "топорных" решений. Но без этого, в мире гигантов мы останемся карликами.
Глобализация заканчивается. Начинается эра мастеров. И она уже идёт, прямо здесь и сейчас.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥3
История технологий сегодня — 23 Февраля
🇷🇺Россия — День защитника Отечества🫡
День защитника Отечества — праздник, отмечаемый ежегодно 23 февраля в России, Беларуси, Казахстане, Кыргызстане, Таджикистане, а также в частично признанных Абхазии, Южной Осетии и непризнанной Приднестровской Молдавской Республике (ПМР).
23 февраля (н. ст.) 1918 года было опубликовано воззвание СНК от 21 февраля «Социалистическое отечество в опасности!», а также «Воззвание Военного главнокомандующего» Н. В. Крыленко.
Этот день был объявлен праздником в РСФСР 27 января 1922 года, когда Президиум ВЦИК РСФСР опубликовал постановление о четвёртой годовщине Красной армии, в котором говорилось: «В соответствии с постановлением IX Всероссийского съезда Советов о Красной армии Президиум ВЦИК обращает внимание исполкомов на наступающую годовщину создания Красной армии (23 февраля)».
С 1922 года в СССР эта дата ежегодно традиционно отмечалась как «День Красной армии», с 1946 года — «День Советской армии», с 1949 по 1992 годы — «День Советской армии и Военно-морского флота».
ℹ️ Кто родился в этот день
Деррик Генри «Дик» Лемер (англ. Derrick Henry Lehmer; 23 февраля 1905, Беркли (Калифорния) — 22 мая 1991, Беркли (Калифорния)) — американский математик, усовершенствовавший работу Эдуарда Люка в 1930-е годы и разработавший Тест Люка — Лемера для простых чисел Мерсенна. Карьера Лемера развивалась в области теории чисел. Во время Великой Депрессии он со своей женой был вынужден сменить множество профессий как в Соединённых Штатах, так и за рубежом, что в конечном итоге случайно привело его в центр исследований в области ранней электронной вычислительной техники.
Роберт Николас Кристиан Топала (англ. Robert Nicholas Christian Topala; род. 23 февраля 1987, Уппландс Весбю, Швеция), более известный как RobTop, — независимый шведский разработчик видеоигр, аниматор и музыкант, прославившийся платформером Geometry Dash.
Аллан Маклауд Кормак (англ. Allan McLeod Cormack; 23 февраля 1924, Йоханнесбург, Южная Африка — 7 мая 1998, Уинчестер, штат Массачусетс, США) — южноафриканский и американский физик, лауреат Нобелевской премии по физиологии и медицине 1979 года «за разработку компьютерной томографии», которую он получил с Годфри Хаунсфилдом.
🌐 Знаковые события
1987 — вспышка сверхновой SN 1987A достигла Земли. Это самая близкая сверхновая со времён изобретения телескопа.
1993 — создан язык программирования Ruby.
#Biography #Birth_Date #Events #23февраля
🇷🇺Россия — День защитника Отечества
День защитника Отечества — праздник, отмечаемый ежегодно 23 февраля в России, Беларуси, Казахстане, Кыргызстане, Таджикистане, а также в частично признанных Абхазии, Южной Осетии и непризнанной Приднестровской Молдавской Республике (ПМР).
23 февраля (н. ст.) 1918 года было опубликовано воззвание СНК от 21 февраля «Социалистическое отечество в опасности!», а также «Воззвание Военного главнокомандующего» Н. В. Крыленко.
Этот день был объявлен праздником в РСФСР 27 января 1922 года, когда Президиум ВЦИК РСФСР опубликовал постановление о четвёртой годовщине Красной армии, в котором говорилось: «В соответствии с постановлением IX Всероссийского съезда Советов о Красной армии Президиум ВЦИК обращает внимание исполкомов на наступающую годовщину создания Красной армии (23 февраля)».
С 1922 года в СССР эта дата ежегодно традиционно отмечалась как «День Красной армии», с 1946 года — «День Советской армии», с 1949 по 1992 годы — «День Советской армии и Военно-морского флота».
Деррик Генри «Дик» Лемер (англ. Derrick Henry Lehmer; 23 февраля 1905, Беркли (Калифорния) — 22 мая 1991, Беркли (Калифорния)) — американский математик, усовершенствовавший работу Эдуарда Люка в 1930-е годы и разработавший Тест Люка — Лемера для простых чисел Мерсенна. Карьера Лемера развивалась в области теории чисел. Во время Великой Депрессии он со своей женой был вынужден сменить множество профессий как в Соединённых Штатах, так и за рубежом, что в конечном итоге случайно привело его в центр исследований в области ранней электронной вычислительной техники.
Роберт Николас Кристиан Топала (англ. Robert Nicholas Christian Topala; род. 23 февраля 1987, Уппландс Весбю, Швеция), более известный как RobTop, — независимый шведский разработчик видеоигр, аниматор и музыкант, прославившийся платформером Geometry Dash.
Аллан Маклауд Кормак (англ. Allan McLeod Cormack; 23 февраля 1924, Йоханнесбург, Южная Африка — 7 мая 1998, Уинчестер, штат Массачусетс, США) — южноафриканский и американский физик, лауреат Нобелевской премии по физиологии и медицине 1979 года «за разработку компьютерной томографии», которую он получил с Годфри Хаунсфилдом.
1987 — вспышка сверхновой SN 1987A достигла Земли. Это самая близкая сверхновая со времён изобретения телескопа.
1993 — создан язык программирования Ruby.
#Biography #Birth_Date #Events #23февраля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4