Поиск наиболее частого элемента
Для поиска моды (наиболее частого элемента) используем хеш-таблицу для подсчета частот:
Пространственная сложность — O(k), где k — количество уникальных авторов. Если элемент составляет строгое большинство (> n/2), эффективнее алгоритм Бойера-Мура, который находит кандидата за O(n) времени и O(1) памяти:
Принцип: один сложный проход против нескольких простых
Константные факторы имеют значение
Хотя с точки зрения асимптотической нотации 2*O(n) = O(n), на практике константные множители существенны.
Рассмотрим обработку массива из 10 миллионов элементов:
Два последовательных прохода: 20 миллионов операций чтения, двойные накладные расходы на управление циклом, потенциально двойное количество кэш-промахов.
Один сложный проход: 10 миллионов операций чтения, но больше вычислений на элемент.
Если один проход в 1.3 раза "тяжелее" на элемент, но избавляет от второго прохода, общее время: 1.3T против 2T — выигрыш ~35%.
Использование кэша процессора
Современные процессоры имеют иерархию памяти: кэш L1 (1-2 нс), L2 (3-10 нс), L3 (10-20 нс), основная память (80-100 нс). Однопроходные алгоритмы лучше используют пространственную локальность: данные, прочитанные в кэш, сразу используются для всех необходимых вычислений.
При двух проходах между ними могут проходить миллисекунды, и данные уже эвакуируются из кэша, требуя повторной загрузки из медленной памяти.
Комплексная агрегация за один проход
Многие задачи можно решить за один проход, комбинируя несколько агрегаций:
Практическое применение
Потоковая обработка данных
Однопроходные алгоритмы — основа систем обработки потоков (Apache Kafka, Apache Flink, Apache Storm). Они позволяют вычислять скользящие средние, агрегировать метрики в реальном времени, обнаруживать аномалии без хранения всего потока.
Анализ больших данных
В MapReduce и подобных фреймворках комбинаторы (combiners) используют однопроходные агрегации для уменьшения объема передаваемых данных. Вместо передачи всех значений, каждый узел предварительно агрегирует свою порцию.
Мониторинг и телеметрия
Системы мониторинга (Prometheus, InfluxDB) вычисляют метрики на лету, используя однопроходные алгоритмы для экономии памяти и процессорного времени.
Ограничения и предостережения
Не все задачи решаемы за один проход.
Например:
Поиск медианы требует хранения хотя бы части данных
Вычисление корреляции между двумя потоками требует их синхронизации
Некоторые статистики (квантили) требуют случайного доступа к данным
Однопроходные алгоритмы часто являются приближенными или требуют компромиссов между точностью и эффективностью.
#Java #для_новичков #beginner #algorithm #line_search
Для поиска моды (наиболее частого элемента) используем хеш-таблицу для подсчета частот:
public static String mostFrequentAuthor(String[] authors) {
Map<String, Integer> freq = new HashMap<>();
String mostFreq = null;
int maxCount = 0;
for (String author : authors) {
int count = freq.getOrDefault(author, 0) + 1;
freq.put(author, count);
if (count > maxCount) {
maxCount = count;
mostFreq = author;
}
}
return mostFreq;
}Пространственная сложность — O(k), где k — количество уникальных авторов. Если элемент составляет строгое большинство (> n/2), эффективнее алгоритм Бойера-Мура, который находит кандидата за O(n) времени и O(1) памяти:
public static String majorityElement(String[] arr) {
String candidate = null;
int count = 0;
for (String s : arr) {
if (count == 0) {
candidate = s;
count = 1;
} else if (s.equals(candidate)) {
count++;
} else {
count--;
}
}
// Второй проход для проверки (тоже O(n))
return candidate; // если гарантировано наличие большинства
}Принцип: один сложный проход против нескольких простых
Константные факторы имеют значение
Хотя с точки зрения асимптотической нотации 2*O(n) = O(n), на практике константные множители существенны.
Рассмотрим обработку массива из 10 миллионов элементов:
Два последовательных прохода: 20 миллионов операций чтения, двойные накладные расходы на управление циклом, потенциально двойное количество кэш-промахов.
Один сложный проход: 10 миллионов операций чтения, но больше вычислений на элемент.
Если один проход в 1.3 раза "тяжелее" на элемент, но избавляет от второго прохода, общее время: 1.3T против 2T — выигрыш ~35%.
Использование кэша процессора
Современные процессоры имеют иерархию памяти: кэш L1 (1-2 нс), L2 (3-10 нс), L3 (10-20 нс), основная память (80-100 нс). Однопроходные алгоритмы лучше используют пространственную локальность: данные, прочитанные в кэш, сразу используются для всех необходимых вычислений.
При двух проходах между ними могут проходить миллисекунды, и данные уже эвакуируются из кэша, требуя повторной загрузки из медленной памяти.
Комплексная агрегация за один проход
Многие задачи можно решить за один проход, комбинируя несколько агрегаций:
public class CombinedStats {
int min, max, count;
long sum;
public void process(int value) {
if (value < min) min = value;
if (value > max) max = value;
sum += value;
count++;
}
public double average() {
return (double) sum / count;
}
}
Такой подход особенно ценен при обработке потоковых данных, где невозможно хранить историю.Практическое применение
Потоковая обработка данных
Однопроходные алгоритмы — основа систем обработки потоков (Apache Kafka, Apache Flink, Apache Storm). Они позволяют вычислять скользящие средние, агрегировать метрики в реальном времени, обнаруживать аномалии без хранения всего потока.
Анализ больших данных
В MapReduce и подобных фреймворках комбинаторы (combiners) используют однопроходные агрегации для уменьшения объема передаваемых данных. Вместо передачи всех значений, каждый узел предварительно агрегирует свою порцию.
Мониторинг и телеметрия
Системы мониторинга (Prometheus, InfluxDB) вычисляют метрики на лету, используя однопроходные алгоритмы для экономии памяти и процессорного времени.
Ограничения и предостережения
Не все задачи решаемы за один проход.
Например:
Поиск медианы требует хранения хотя бы части данных
Вычисление корреляции между двумя потоками требует их синхронизации
Некоторые статистики (квантили) требуют случайного доступа к данным
Однопроходные алгоритмы часто являются приближенными или требуют компромиссов между точностью и эффективностью.
#Java #для_новичков #beginner #algorithm #line_search
👍3
Что выведет код?
#Tasks
import java.util.List;
public class Task150126 {
public static void main(String[] args) {
List<String> data = List.of("A", "B", "C");
long count = data.stream()
.peek(s -> System.out.print(s))
.map(s -> s + s)
.count();
System.out.print(count);
}
}
#Tasks
👍1
👍1🔥1😱1
Почему DTO важны даже в маленьких проектах? 🤓
Ответ:
DTO изолируют API от доменной модели.
Это упрощает изменения, повышает безопасность и предотвращает утечку внутренней структуры.
Отказ от DTO почти всегда приводит к проблемам при росте проекта.
#собеседование
Ответ:
Это упрощает изменения, повышает безопасность и предотвращает утечку внутренней структуры.
Отказ от DTO почти всегда приводит к проблемам при росте проекта.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2 1
Please open Telegram to view this post
VIEW IN TELEGRAM
Хабр
Осознанная стоимость абстракций: Autoboxing в современной Java
Мы живём во времена, когда на оперативной памяти для heap Java-приложений почти не экономят, а архитектурные решения, которые ещё недавно можно было назвать расточительными, всё чаще воспринимаются...
👍9
История IT-технологий сегодня — 16 января
ℹ️ Кто родился в этот день
Не нашел(
🌐 Знаковые события
1973 — «Луноход-2» отправился в путешествие по поверхности Луны.
1986 — анонс Macintosh Plus. Он был третьей моделью в линейке Macintosh, представленной через два года после оригинального Macintosh и чуть более чем через год после Macintosh 512K , по цене 2599 долларов США. В качестве эволюционного улучшения по сравнению с 512K он поставлялся со стандартным 1 МБ оперативной памяти, расширяемой до 4 МБ, и внешней шиной SCSI , а также с другими небольшими улучшениями. Первоначально корпус компьютера был того же бежевого цвета, что и оригинальный Macintosh, Pantone 453; однако в 1987 году цвет корпуса был изменен на долговечный теплый серый цвет «Платина». Это самая ранняя модель Macintosh, способная запускать системное программное обеспечение 5 , 6 и 7 , вплоть до System 7.5.5, но не System 7.5.2.
#Biography #Birth_Date #Events #16Января
Не нашел(
1973 — «Луноход-2» отправился в путешествие по поверхности Луны.
1986 — анонс Macintosh Plus. Он был третьей моделью в линейке Macintosh, представленной через два года после оригинального Macintosh и чуть более чем через год после Macintosh 512K , по цене 2599 долларов США. В качестве эволюционного улучшения по сравнению с 512K он поставлялся со стандартным 1 МБ оперативной памяти, расширяемой до 4 МБ, и внешней шиной SCSI , а также с другими небольшими улучшениями. Первоначально корпус компьютера был того же бежевого цвета, что и оригинальный Macintosh, Pantone 453; однако в 1987 году цвет корпуса был изменен на долговечный теплый серый цвет «Платина». Это самая ранняя модель Macintosh, способная запускать системное программное обеспечение 5 , 6 и 7 , вплоть до System 7.5.5, но не System 7.5.2.
#Biography #Birth_Date #Events #16Января
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Раздел 7. Алгоритмы
Глава 2. Линейные алгоритмы и один проход
Практика:
Подсчитать общее количество книг, средний год издания.
Найти самого плодовитого автора.
Задача со звездочкой: Найти двух авторов с наименьшим количеством книг за один проход.
Мы реализуем:
Подсчет общего количества книг.
Вычисление среднего года издания.
Поиск самого плодовитого автора (с наибольшим количеством книг).
Задача со звездочкой: поиск двух авторов с наименьшим количеством книг за один проход.
В конце проведем анализ: почему всё решается за O(n), зачем не нужна сортировка и что изменится при увеличении данных в 1000 раз.
Подготовка к уроку
Убедитесь, что проект готов:
Класс Book с полями title, author, year (геттеры есть).
Класс Library с List<Book> books (ArrayList или CopyOnWriteArrayList из предыдущего урока).
Методы добавления книг и вывода.
Откройте Library.java.
Импорты: Убедитесь, что есть import java.util.HashMap; (для подсчета авторов) и import java.util.Map;.
Реализация подсчета общего количества книг и среднего года
Создайте метод countBooks():
Возвращает int — размер списка книг.
Просто используйте books.size().
Создайте метод calculateAverageYear():
Возвращает double (средний год).
Инициализируйте переменные: int totalYear = 0; int count = 0;
В цикле for-each по books:
totalYear += book.getYear();
count++;
Если count == 0 — верните 0 или бросьте исключение.
Возвращает (double) totalYear / count.
Реализация поиска самого плодовитого автора
Создайте метод findMostProductiveAuthor():
Возвращает String — имя автора с наибольшим количеством книг.
Используйте HashMap<String, Integer> для подсчета: ключ — author, значение — количество книг.
В одном проходе по books:
String author = book.getAuthor();
Если author null — пропустите или обработайте.
map.put(author, map.getOrDefault(author, 0) + 1);
После цикла найдите автора с максимальным значением:
String maxAuthor = null;
int maxCount = 0;
Переберите map.entrySet() — найдите max.
Верните maxAuthor (или "Нет авторов", если пусто).
Задача со звездочкой: Два автора с наименьшим количеством книг за один проход
Создайте метод findTwoLeastProductiveAuthors():
Возвращает массив String[2] или List<String> с двумя авторами (или меньше, если авторов мало).
Используйте HashMap<String, Integer> для подсчета, как выше.
После подсчета найдите двух авторов с минимальным количеством книг.
Варианты:
Перебрать map.entrySet() два раза: сначала найти min, потом второй min.
Или собрать все пары в List<Map.Entry<String, Integer>>, отсортировать (но это O(n log n) — не за один проход).
За один проход: Поддерживайте две переменные min1 и min2 (String и count), обновляйте их при переборе map.
Верните двух авторов (или один, если авторов меньше 2).
#Java #для_новичков #beginner #algorithm #Практика
Глава 2. Линейные алгоритмы и один проход
Практика:
Подсчитать общее количество книг, средний год издания.
Найти самого плодовитого автора.
Задача со звездочкой: Найти двух авторов с наименьшим количеством книг за один проход.
Мы реализуем:
Подсчет общего количества книг.
Вычисление среднего года издания.
Поиск самого плодовитого автора (с наибольшим количеством книг).
Задача со звездочкой: поиск двух авторов с наименьшим количеством книг за один проход.
В конце проведем анализ: почему всё решается за O(n), зачем не нужна сортировка и что изменится при увеличении данных в 1000 раз.
Подготовка к уроку
Убедитесь, что проект готов:
Класс Book с полями title, author, year (геттеры есть).
Класс Library с List<Book> books (ArrayList или CopyOnWriteArrayList из предыдущего урока).
Методы добавления книг и вывода.
Откройте Library.java.
Импорты: Убедитесь, что есть import java.util.HashMap; (для подсчета авторов) и import java.util.Map;.
Реализация подсчета общего количества книг и среднего года
Создайте метод countBooks():
Возвращает int — размер списка книг.
Просто используйте books.size().
Создайте метод calculateAverageYear():
Возвращает double (средний год).
Инициализируйте переменные: int totalYear = 0; int count = 0;
В цикле for-each по books:
totalYear += book.getYear();
count++;
Если count == 0 — верните 0 или бросьте исключение.
Возвращает (double) totalYear / count.
Реализация поиска самого плодовитого автора
Создайте метод findMostProductiveAuthor():
Возвращает String — имя автора с наибольшим количеством книг.
Используйте HashMap<String, Integer> для подсчета: ключ — author, значение — количество книг.
В одном проходе по books:
String author = book.getAuthor();
Если author null — пропустите или обработайте.
map.put(author, map.getOrDefault(author, 0) + 1);
После цикла найдите автора с максимальным значением:
String maxAuthor = null;
int maxCount = 0;
Переберите map.entrySet() — найдите max.
Верните maxAuthor (или "Нет авторов", если пусто).
Задача со звездочкой: Два автора с наименьшим количеством книг за один проход
Создайте метод findTwoLeastProductiveAuthors():
Возвращает массив String[2] или List<String> с двумя авторами (или меньше, если авторов мало).
Используйте HashMap<String, Integer> для подсчета, как выше.
После подсчета найдите двух авторов с минимальным количеством книг.
Варианты:
Перебрать map.entrySet() два раза: сначала найти min, потом второй min.
Или собрать все пары в List<Map.Entry<String, Integer>>, отсортировать (но это O(n log n) — не за один проход).
За один проход: Поддерживайте две переменные min1 и min2 (String и count), обновляйте их при переборе map.
Верните двух авторов (или один, если авторов меньше 2).
#Java #для_новичков #beginner #algorithm #Практика
👍2🔥1
Анализ алгоритмов (объемно)
Сложность всех задач:
Подсчет количества и среднего года: O(n) — один проход по списку.
Самый плодовитый автор: O(n) — один проход + O(n) на поиск max в map (всего O(n)).
Два наименьших: O(n) — один проход + O(n) на поиск двух min (всего O(n)).
Почему не нужна сортировка:
Сортировка — O(n log n), но мы решаем задачу за O(n).
Для max/min достаточно одного прохода с переменными (или map).
Сортировка нужна только для полного упорядочивания (например, топ-10).
Что изменится при увеличении данных в 1000 раз:
Исходный n = 1000 книг → O(n) = 1000 операций.
n = 1 000 000 книг → O(n) = 1 млн операций — всё равно быстро (миллисекунды на современном ПК).
O(n log n) сортировка на 1 млн — ~20 млн операций — в 20 раз медленнее.
Память: HashMap — O(n) для авторов (если авторов много — тоже O(n)).
Вывод: O(n) алгоритмы масштабируются линейно — идеально для больших данных.
Тестирование и отладка
Добавьте книги:
В Main добавьте 10–15 книг с повторяющимися авторами (3–4 автора).
Протестируйте:
Вызовите countBooks() — проверьте размер.
calculateAverageYear() — посчитайте вручную и сравните.
findMostProductiveAuthor() — проверьте, кто лидер.
findTwoLeastProductiveAuthors() — найдите двух с минимумом книг.
Отладка:
Breakpoint в циклах — смотрите map.size() и max/min.
Если авторы null — добавьте проверку.
Полезные советы для новичков
Один проход: Всегда старайтесь решать за O(n) — эффективно и просто.
HashMap для подсчета: Лучший способ для частот.
Null: Проверяйте author != null.
Точность среднего: Используйте double.
Расширение: Добавьте метод topAuthors(int n) — используйте PriorityQueue.
Практическое задание
Задача 1: Добавьте метод getBooksCountByAuthor(String author) — использует map для подсчета.
Задача 2: Реализуйте findAuthorsWithMoreThan(int count) — возвращает List<String> авторов с >count книг.
Задача 3: В Main добавьте 20 книг, вызовите все методы — проверьте результаты.
#Java #для_новичков #beginner #algorithm #Практика
Сложность всех задач:
Подсчет количества и среднего года: O(n) — один проход по списку.
Самый плодовитый автор: O(n) — один проход + O(n) на поиск max в map (всего O(n)).
Два наименьших: O(n) — один проход + O(n) на поиск двух min (всего O(n)).
Почему не нужна сортировка:
Сортировка — O(n log n), но мы решаем задачу за O(n).
Для max/min достаточно одного прохода с переменными (или map).
Сортировка нужна только для полного упорядочивания (например, топ-10).
Что изменится при увеличении данных в 1000 раз:
Исходный n = 1000 книг → O(n) = 1000 операций.
n = 1 000 000 книг → O(n) = 1 млн операций — всё равно быстро (миллисекунды на современном ПК).
O(n log n) сортировка на 1 млн — ~20 млн операций — в 20 раз медленнее.
Память: HashMap — O(n) для авторов (если авторов много — тоже O(n)).
Вывод: O(n) алгоритмы масштабируются линейно — идеально для больших данных.
Тестирование и отладка
Добавьте книги:
В Main добавьте 10–15 книг с повторяющимися авторами (3–4 автора).
Протестируйте:
Вызовите countBooks() — проверьте размер.
calculateAverageYear() — посчитайте вручную и сравните.
findMostProductiveAuthor() — проверьте, кто лидер.
findTwoLeastProductiveAuthors() — найдите двух с минимумом книг.
Отладка:
Breakpoint в циклах — смотрите map.size() и max/min.
Если авторы null — добавьте проверку.
Полезные советы для новичков
Один проход: Всегда старайтесь решать за O(n) — эффективно и просто.
HashMap для подсчета: Лучший способ для частот.
Null: Проверяйте author != null.
Точность среднего: Используйте double.
Расширение: Добавьте метод topAuthors(int n) — используйте PriorityQueue.
Практическое задание
Задача 1: Добавьте метод getBooksCountByAuthor(String author) — использует map для подсчета.
Задача 2: Реализуйте findAuthorsWithMoreThan(int count) — возвращает List<String> авторов с >count книг.
Задача 3: В Main добавьте 20 книг, вызовите все методы — проверьте результаты.
#Java #для_новичков #beginner #algorithm #Практика
👍2🔥1
Что выведет код?
#Tasks
import java.util.List;
public class Task160126 {
public static void main(String[] args) {
List<String> data = List.of("apple", "banana");
boolean result = data.stream()
.filter(s -> s.length() > 10)
.allMatch(s -> {
System.out.print("check ");
return s.startsWith("a");
});
System.out.print(result);
}
}
#Tasks
👍1
😱1
Почему Entity нельзя напрямую отдавать в REST? 🤓
Ответ:
Entity привязаны к persistence-контексту, содержат ленивые связи и аннотации ORM.
Это приводит к N+1, LazyInitializationException и утечке внутренней модели. DTO решают эти проблемы.
#собеседование
Ответ:
Это приводит к N+1, LazyInitializationException и утечке внутренней модели. DTO решают эти проблемы.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🍾3
История IT-технологий сегодня — 17 января
ℹ️ Кто родился в этот день
Анита Борг (англ. Anita Borg Naffz; 17 января 1949 — 6 апреля 2003) — американская учёная в области компьютерных технологий и вычислений. Анита родилась в Чикаго, штат Иллинойс, росла в Палатине, штат Иллинойс, а затем в Kaneohe на Гавайях и в Мукилтео (Mukilteo), Вашингтон. Основала Институт женщин и технологий (ныне AnitaB.org) и конференцию Grace Hopper Celebration. Она работала над операционными системами и высокопроизводительными вычислениями в Digital Equipment Corp (DEC), занимаясь вопросами архитектуры памяти.
Бе́нджамин Фра́нклин (англ. Benjamin Franklin [ˈbɛndʒəmɪn ˈfɹæŋklɪn]; 17 января 1706, Бостон, Провинция Массачусетс-Бэй, Британская империя — 17 апреля 1790, Филадельфия, Пенсильвания, США) — американский политический деятель, дипломат, изобретатель, учёный, философ, писатель, масон, полимат. Одна из самых влиятельных фигур XVIII века. Его эксперименты с электричеством привели к открытию закона сохранения заряда и введению терминов «положительный» и «отрицательный». Вся современная двоичная логика и работа транзисторов физически базируются на концепции заряда, предложенной Франклином.
🌐 Знаковые события
1969 — Возвращение корабля «Союз-4». После первой в истории успешной стыковки и перехода экипажа, 17 января Владимир Шаталов успешно приземлился. Это был триумф советской космической программы, доказавший возможность сборки станций на орбите.
#Biography #Birth_Date #Events #17Января
Анита Борг (англ. Anita Borg Naffz; 17 января 1949 — 6 апреля 2003) — американская учёная в области компьютерных технологий и вычислений. Анита родилась в Чикаго, штат Иллинойс, росла в Палатине, штат Иллинойс, а затем в Kaneohe на Гавайях и в Мукилтео (Mukilteo), Вашингтон. Основала Институт женщин и технологий (ныне AnitaB.org) и конференцию Grace Hopper Celebration. Она работала над операционными системами и высокопроизводительными вычислениями в Digital Equipment Corp (DEC), занимаясь вопросами архитектуры памяти.
Бе́нджамин Фра́нклин (англ. Benjamin Franklin [ˈbɛndʒəmɪn ˈfɹæŋklɪn]; 17 января 1706, Бостон, Провинция Массачусетс-Бэй, Британская империя — 17 апреля 1790, Филадельфия, Пенсильвания, США) — американский политический деятель, дипломат, изобретатель, учёный, философ, писатель, масон, полимат. Одна из самых влиятельных фигур XVIII века. Его эксперименты с электричеством привели к открытию закона сохранения заряда и введению терминов «положительный» и «отрицательный». Вся современная двоичная логика и работа транзисторов физически базируются на концепции заряда, предложенной Франклином.
1969 — Возвращение корабля «Союз-4». После первой в истории успешной стыковки и перехода экипажа, 17 января Владимир Шаталов успешно приземлился. Это был триумф советской космической программы, доказавший возможность сборки станций на орбите.
#Biography #Birth_Date #Events #17Января
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
С 10.01 по 16.01
Предыдущий пост(с 27.12 по 09.01)
Воскресный мотивационный пост:
не было мотивации
Запись встреч/видео:
Telegram AI Bot. Версия Telegram API 9.3+
Обучающие статьи:
Java:
Раздел 7. Алгоритмы
Глава 1: Основы анализа алгоритмов
Пространственная сложность и компромиссы
Линейный поиск и его ниша
Агрегация за один проход: максимум эффективности
Практика
Глубокая архитектура и внутреннее устройство RabbitMQ
Обработка ошибок и мониторинг RabbitMQ
Полезные статьи и видео:
ПОДКЛЮЧЕНИЕ GPT GO на ГОД!
Осознанная стоимость абстракций: Autoboxing в современной Java
Перевод Spring Boot приложения с HTTP на HTTPS без ругани браузера
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
Предыдущий пост(с 27.12 по 09.01)
Воскресный мотивационный пост:
не было мотивации
Запись встреч/видео:
Telegram AI Bot. Версия Telegram API 9.3+
Обучающие статьи:
Java:
Раздел 7. Алгоритмы
Глава 1: Основы анализа алгоритмов
Пространственная сложность и компромиссы
Линейный поиск и его ниша
Агрегация за один проход: максимум эффективности
Практика
Глубокая архитектура и внутреннее устройство RabbitMQ
Обработка ошибок и мониторинг RabbitMQ
Полезные статьи и видео:
ПОДКЛЮЧЕНИЕ GPT GO на ГОД!
Осознанная стоимость абстракций: Autoboxing в современной Java
Перевод Spring Boot приложения с HTTP на HTTPS без ругани браузера
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
👍3 1
История IT-технологий сегодня — 18 января
ℹ️ Кто родился в этот день
Рэй Милтон Долби (англ. Ray Milton Dolby; 18 января 1933, Портленд — 12 сентября 2013, Сан-Франциско) — американский инженер и изобретатель. Вошёл в историю как разработчик системы шумопонижения, получившей его имя. Логотип Dolby значился на миллионах единиц звукозаписывающего оборудования и аудиокассет, производившихся в мире на протяжении нескольких десятилетий.
🌐 Знаковые события
2012 — Википедия на одни сутки закрыла доступ к своему англоязычному сайту в знак протеста против обсуждаемого в США законопроекта о борьбе с интернет-пиратством.
#Biography #Birth_Date #Events #18Января
Рэй Милтон Долби (англ. Ray Milton Dolby; 18 января 1933, Портленд — 12 сентября 2013, Сан-Франциско) — американский инженер и изобретатель. Вошёл в историю как разработчик системы шумопонижения, получившей его имя. Логотип Dolby значился на миллионах единиц звукозаписывающего оборудования и аудиокассет, производившихся в мире на протяжении нескольких десятилетий.
2012 — Википедия на одни сутки закрыла доступ к своему англоязычному сайту в знак протеста против обсуждаемого в США законопроекта о борьбе с интернет-пиратством.
#Biography #Birth_Date #Events #18Января
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
2. Миграции с Flyway и LiquiBase. Основы управления БД
Это не очередной tutorial по настройке Flyway. Это инженерный разбор двух подходов к управлению БД, с реальными примерами на Spring Boot и PostgreSQL.
Я покажу:
🔹 Почему @Entity ≠ схема БД и чем это опасно на проде
🔹 Как Hibernate "ломает" данные при ddl-auto=update (живая демонстрация с падением!)
🔹 Полное сравнение Flyway vs Liquibase — философия, плюсы, минусы
🔹 REAL-WORLD примеры миграций для существующего проекта OrderHub
🔹 Ошибки, с которыми столкнулся лично я, и как их исправить
🔹 И немного дебага как всегда)
Исходный код проекта на GitHub очень ждет Ваших звезд.
Ссылка на Youtube
Ссылка на Рутьюб
Смотрите, ставьте лайки, подписывайтесь на каналы!✌️
Это не очередной tutorial по настройке Flyway. Это инженерный разбор двух подходов к управлению БД, с реальными примерами на Spring Boot и PostgreSQL.
Я покажу:
🔹 Почему @Entity ≠ схема БД и чем это опасно на проде
🔹 Как Hibernate "ломает" данные при ddl-auto=update (живая демонстрация с падением!)
🔹 Полное сравнение Flyway vs Liquibase — философия, плюсы, минусы
🔹 REAL-WORLD примеры миграций для существующего проекта OrderHub
🔹 Ошибки, с которыми столкнулся лично я, и как их исправить
🔹 И немного дебага как всегда)
Исходный код проекта на GitHub очень ждет Ваших звезд.
Ссылка на Youtube
Ссылка на Рутьюб
Смотрите, ставьте лайки, подписывайтесь на каналы!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥2 1
История IT-технологий сегодня — 19 января
ℹ️ Кто родился в этот день
Леони́д Вита́льевич Канторо́вич (19 января 1912[9], Санкт-Петербург — 7 апреля 1986, Москва) — советский математик и экономист, один из создателей линейного программирования. Лауреат премии по экономике памяти Альфреда Нобеля 1975 года «за вклад в теорию оптимального распределения ресурсов». Академик АН СССР (1964), доктор физико-математических наук (1935), профессор.
🌐 Знаковые события
1978 — основан институт Санкт-Петербургский институт информатики и автоматизации РАН.
1983 — Apple представила один из первых персональных компьютеров с графическим интерфейсом (GUI) и мышью. Несмотря на коммерческий провал из-за цены в $10 000, именно Lisa проложила путь для Macintosh и Windows. Она ввела такие понятия, как «рабочий стол», «иконки» и «окна».
#Biography #Birth_Date #Events #19Января
Леони́д Вита́льевич Канторо́вич (19 января 1912[9], Санкт-Петербург — 7 апреля 1986, Москва) — советский математик и экономист, один из создателей линейного программирования. Лауреат премии по экономике памяти Альфреда Нобеля 1975 года «за вклад в теорию оптимального распределения ресурсов». Академик АН СССР (1964), доктор физико-математических наук (1935), профессор.
1978 — основан институт Санкт-Петербургский институт информатики и автоматизации РАН.
1983 — Apple представила один из первых персональных компьютеров с графическим интерфейсом (GUI) и мышью. Несмотря на коммерческий провал из-за цены в $10 000, именно Lisa проложила путь для Macintosh и Windows. Она ввела такие понятия, как «рабочий стол», «иконки» и «окна».
#Biography #Birth_Date #Events #19Января
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Раздел 7. Алгоритмы
Глава 3: Алгоритмы сортировки и подготовка данных
Назначение и стоимость сортировки: стратегическая инвестиция в данные
Сортировка — это процесс упорядочивания элементов согласно определенному критерию сравнения. Это одна из наиболее изученных и практически значимых операций в информатике, чья важность простирается далеко за пределы простого упорядочивания. Основные цели сортировки можно разделить на три категории.
Ускорение поиска
Главное практическое применение сортировки — обеспечение быстрого поиска. Неотсортированные данные допускают только линейный поиск с временной сложностью O(n). После сортировки становится возможным бинарный поиск, сокращающий время до O(log n). Это преобразует поиск из линейной в логарифмическую операцию, что для миллиона элементов означает сокращение с миллиона сравнений до всего 20.
Улучшение представления данных
Сортировка делает данные понятными для человека. Пользовательские интерфейсы, отчеты, лог-файлы — везде отсортированные данные воспринимаются легче. Сортировка по алфавиту, дате, приоритету или релевантности — это не техническая необходимость, а требование человеко-компьютерного взаимодействия.
Обеспечение группировки и агрегации
Сортировка является предварительным шагом для многих алгоритмов анализа данных.
После сортировки идентичные или схожие элементы располагаются рядом, что упрощает:
Удаление дубликатов за один проход
Построение гистограмм и частотных распределений
Выполнение операций слияния (как в MergeSort)
Реализацию алгоритмов слияния интервалов или поиска пересечений
Сортировка как стратегическая инвестиция
Сортировку можно рассматривать как инвестицию с отложенной выгодой. Мы платим относительно высокую первоначальную цену — O(n log n) операций — чтобы получить ускорение в будущих операциях. Эта модель окупается, когда количество операций поиска значительно превышает единицу.
Рассмотрим математическую модель:
Стоимость сортировки: C₁ × n log n
Стоимость одного линейного поиска: C₂ × n
Стоимость одного бинарного поиска: C₃ × log n
Точка безубыточности наступает, когда k операций бинарного поиска после сортировки становятся выгоднее k операций линейного поиска без сортировки:
C₁ × n log n + k × C₃ × log n < k × C₂ × n
Для типичных значений (n=1000, C₁≈C₂≈C₃) получаем, что уже при 10-15 операциях поиска сортировка окупается.
Оптимизация для повторного использования
Отсортированные данные становятся активом, который можно многократно использовать для различных целей.
Один раз отсортировав массив сотрудников по фамилии, мы получаем возможность:
Быстрого поиска конкретного сотрудника
Генерации алфавитного списка
Поиска сотрудников в заданном алфавитном диапазоне
Объединения с другим отсортированным списком
Это преобразует данные из пассивного состояния в активную структуру, поддерживающую множество операций.
#Java #для_новичков #beginner #algorithm #sorted
Глава 3: Алгоритмы сортировки и подготовка данных
Назначение и стоимость сортировки: стратегическая инвестиция в данные
Сортировка — это процесс упорядочивания элементов согласно определенному критерию сравнения. Это одна из наиболее изученных и практически значимых операций в информатике, чья важность простирается далеко за пределы простого упорядочивания. Основные цели сортировки можно разделить на три категории.
Ускорение поиска
Главное практическое применение сортировки — обеспечение быстрого поиска. Неотсортированные данные допускают только линейный поиск с временной сложностью O(n). После сортировки становится возможным бинарный поиск, сокращающий время до O(log n). Это преобразует поиск из линейной в логарифмическую операцию, что для миллиона элементов означает сокращение с миллиона сравнений до всего 20.
// Демонстрация разницы в поиске
public class SearchComparison {
// Линейный поиск в неотсортированном массиве
public static int linearSearch(int[] array, int target) {
for (int i = 0; i < array.length; i++) {
if (array[i] == target) return i;
}
return -1;
}
// Бинарный поиск в отсортированном массиве
public static int binarySearch(int[] sortedArray, int target) {
int left = 0, right = sortedArray.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (sortedArray[mid] == target) return mid;
if (sortedArray[mid] < target) left = mid + 1;
else right = mid - 1;
}
return -1;
}
}
Улучшение представления данных
Сортировка делает данные понятными для человека. Пользовательские интерфейсы, отчеты, лог-файлы — везде отсортированные данные воспринимаются легче. Сортировка по алфавиту, дате, приоритету или релевантности — это не техническая необходимость, а требование человеко-компьютерного взаимодействия.
Обеспечение группировки и агрегации
Сортировка является предварительным шагом для многих алгоритмов анализа данных.
После сортировки идентичные или схожие элементы располагаются рядом, что упрощает:
Удаление дубликатов за один проход
Построение гистограмм и частотных распределений
Выполнение операций слияния (как в MergeSort)
Реализацию алгоритмов слияния интервалов или поиска пересечений
Сортировка как стратегическая инвестиция
Сортировку можно рассматривать как инвестицию с отложенной выгодой. Мы платим относительно высокую первоначальную цену — O(n log n) операций — чтобы получить ускорение в будущих операциях. Эта модель окупается, когда количество операций поиска значительно превышает единицу.
Рассмотрим математическую модель:
Стоимость сортировки: C₁ × n log n
Стоимость одного линейного поиска: C₂ × n
Стоимость одного бинарного поиска: C₃ × log n
Точка безубыточности наступает, когда k операций бинарного поиска после сортировки становятся выгоднее k операций линейного поиска без сортировки:
C₁ × n log n + k × C₃ × log n < k × C₂ × n
Для типичных значений (n=1000, C₁≈C₂≈C₃) получаем, что уже при 10-15 операциях поиска сортировка окупается.
Оптимизация для повторного использования
Отсортированные данные становятся активом, который можно многократно использовать для различных целей.
Один раз отсортировав массив сотрудников по фамилии, мы получаем возможность:
Быстрого поиска конкретного сотрудника
Генерации алфавитного списка
Поиска сотрудников в заданном алфавитном диапазоне
Объединения с другим отсортированным списком
Это преобразует данные из пассивного состояния в активную структуру, поддерживающую множество операций.
#Java #для_новичков #beginner #algorithm #sorted
👍4
Кэш-дружественность отсортированных данных
Современные процессоры сильно зависят от кэш-памяти. Отсортированные данные обладают лучшей пространственной локальностью: последовательные обращения к памяти с высокой вероятностью попадают в кэш. Это особенно важно для итеративных алгоритмов, где каждый проход по отсортированным данным выполняется на 20-40% быстрее благодаря уменьшению количества кэш-промахов.
Устойчивость сортировки: концепция и практическая ценность
Сортировка называется устойчивой (stable), если она сохраняет относительный порядок элементов с одинаковыми ключами. Формально: если до сортировки элемент A предшествовал элементу B, и их ключи сортировки равны, то после сортировки A останется перед B.
Практический пример: многоуровневая сортировка
Рассмотрим каталог книг с полями: автор, год издания, название. Требуется отсортировать книги по автору, а внутри каждого автора — по году издания.
Без устойчивой сортировки задача требует сложной логики:
С устойчивой сортировкой решение элегантно:
Устойчивость гарантирует, что результат двух последовательных сортировок эквивалентен сортировке составным ключом.
Где устойчивость критически важна
Визуализация данных: При построении графиков, где элементы должны сохранять дополнительную атрибутику после сортировки по значению.
Транзакционные системы: В финансовых приложениях, где порядок одинаковых транзакций должен сохраняться согласно времени поступления.
Обработка последовательностей: В биоинформатике при анализе геномных данных, где относительный порядок элементов с одинаковым весом несет смысловую нагрузку.
Инкрементальная сортировка: При добавлении новых элементов в уже отсортированную коллекцию и последующей повторной сортировке.
Цена устойчивости
Устойчивость обычно достигается за счет:
Дополнительной памяти (как в MergeSort)
Более сложных алгоритмов сравнения
Незначительного увеличения времени выполнения
Неустойчивые алгоритмы (как QuickSort или HeapSort) часто быстрее и используют меньше памяти, но требуют осторожности при работе с составными ключами.
Количественная оценка стоимости сортировки
Стоимость сортировки можно амортизировать на все последующие операции.
Для коллекции из n элементов, над которой выполняется m операций поиска:
Без сортировки: Суммарная стоимость = m × O(n) = O(m × n)
С сортировкой: Суммарная стоимость = O(n log n) + m × O(log n)
Разница становится существенной при m > log n. Для n=1000 (log n ≈ 10) уже при 11 поисках сортировка окупается.
Влияние на системную архитектуру
Решение о предварительной сортировке влияет на проектирование систем:
Пакетная обработка: Сортировка выполняется один раз при загрузке данных, затем используется для множества запросов.
Интерактивные системы: Для часто изменяющихся данных поддерживается индексированная структура (как B-дерево), которая обеспечивает и сортировку, и быстрый поиск.
Распределенные системы: Данные распределяются между узлами уже отсортированными (shard-ключи), что позволяет выполнять параллельный поиск.
#Java #для_новичков #beginner #algorithm #sorted
Современные процессоры сильно зависят от кэш-памяти. Отсортированные данные обладают лучшей пространственной локальностью: последовательные обращения к памяти с высокой вероятностью попадают в кэш. Это особенно важно для итеративных алгоритмов, где каждый проход по отсортированным данным выполняется на 20-40% быстрее благодаря уменьшению количества кэш-промахов.
Устойчивость сортировки: концепция и практическая ценность
Сортировка называется устойчивой (stable), если она сохраняет относительный порядок элементов с одинаковыми ключами. Формально: если до сортировки элемент A предшествовал элементу B, и их ключи сортировки равны, то после сортировки A останется перед B.
Практический пример: многоуровневая сортировка
Рассмотрим каталог книг с полями: автор, год издания, название. Требуется отсортировать книги по автору, а внутри каждого автора — по году издания.
Без устойчивой сортировки задача требует сложной логики:
// Сложный компаратор для неустойчивой сортировки
Comparator<Book> complexComparator = Comparator
.comparing(Book::getAuthor)
.thenComparing(Book::getYear);
books.sort(complexComparator); // Работает, но если сортировка неустойчива,
// порядок внутри автора может нарушиться
С устойчивой сортировкой решение элегантно:
// Сначала сортируем по вторичному ключу
books.sort(Comparator.comparing(Book::getYear));
// Затем сортируем по основному ключу
books.sort(Comparator.comparing(Book::getAuthor));
// После второй сортировки порядок годов сохранится для каждого автора
// благодаря устойчивости
Устойчивость гарантирует, что результат двух последовательных сортировок эквивалентен сортировке составным ключом.
Где устойчивость критически важна
Визуализация данных: При построении графиков, где элементы должны сохранять дополнительную атрибутику после сортировки по значению.
Транзакционные системы: В финансовых приложениях, где порядок одинаковых транзакций должен сохраняться согласно времени поступления.
Обработка последовательностей: В биоинформатике при анализе геномных данных, где относительный порядок элементов с одинаковым весом несет смысловую нагрузку.
Инкрементальная сортировка: При добавлении новых элементов в уже отсортированную коллекцию и последующей повторной сортировке.
Цена устойчивости
Устойчивость обычно достигается за счет:
Дополнительной памяти (как в MergeSort)
Более сложных алгоритмов сравнения
Незначительного увеличения времени выполнения
Неустойчивые алгоритмы (как QuickSort или HeapSort) часто быстрее и используют меньше памяти, но требуют осторожности при работе с составными ключами.
Количественная оценка стоимости сортировки
Стоимость сортировки можно амортизировать на все последующие операции.
Для коллекции из n элементов, над которой выполняется m операций поиска:
Без сортировки: Суммарная стоимость = m × O(n) = O(m × n)
С сортировкой: Суммарная стоимость = O(n log n) + m × O(log n)
Разница становится существенной при m > log n. Для n=1000 (log n ≈ 10) уже при 11 поисках сортировка окупается.
Влияние на системную архитектуру
Решение о предварительной сортировке влияет на проектирование систем:
Пакетная обработка: Сортировка выполняется один раз при загрузке данных, затем используется для множества запросов.
Интерактивные системы: Для часто изменяющихся данных поддерживается индексированная структура (как B-дерево), которая обеспечивает и сортировку, и быстрый поиск.
Распределенные системы: Данные распределяются между узлами уже отсортированными (shard-ключи), что позволяет выполнять параллельный поиск.
#Java #для_новичков #beginner #algorithm #sorted
👍5
Компромисс: сортировка vs индексация
Сортировка — не единственный способ ускорить поиск. Альтернатива — построение индекса (например, хеш-таблицы).
Сравнение:
Сортировка: O(n log n) времени, O(1) дополнительной памяти (in-place), поддерживает диапазонные запросы
Хеширование: O(n) времени, O(n) дополнительной памяти, точечный доступ O(1), нет поддержки диапазонов
Выбор зависит от паттерна доступа: частые диапазонные запросы требуют сортировки, точечные — хеширования.
Практические рекомендации
Когда сортировать данные
Предварительная сортировка: Когда известно, что данные будут многократно использоваться для поиска или анализа.
Кэширование отсортированных представлений: Хранить данные в основной форме, но создавать отсортированные копии для частых запросов.
Ленивая сортировка: Откладывать сортировку до первого запроса, требующего порядка.
Когда избегать сортировки
Единичные операции: Если требуется одна операция поиска, линейный поиск может быть эффективнее.
Частые модификации: При постоянных добавлениях/удалениях поддержание отсортированного состояния требует дополнительных затрат.
Ограниченные ресурсы: На устройствах с ограниченной памятью in-place сортировка предпочтительнее, но может быть слишком дорогой по времени.
Выбор алгоритма сортировки
Критерии выбора:
Устойчивость: Нужна ли сохранение относительного порядка?
Память: Доступна ли дополнительная память O(n)?
Время: Важна ли гарантия O(n log n) в худшем случае?
Данные: Частично отсортированы ли данные?
#Java #для_новичков #beginner #algorithm #sorted
Сортировка — не единственный способ ускорить поиск. Альтернатива — построение индекса (например, хеш-таблицы).
Сравнение:
Сортировка: O(n log n) времени, O(1) дополнительной памяти (in-place), поддерживает диапазонные запросы
Хеширование: O(n) времени, O(n) дополнительной памяти, точечный доступ O(1), нет поддержки диапазонов
Выбор зависит от паттерна доступа: частые диапазонные запросы требуют сортировки, точечные — хеширования.
Практические рекомендации
Когда сортировать данные
Предварительная сортировка: Когда известно, что данные будут многократно использоваться для поиска или анализа.
Кэширование отсортированных представлений: Хранить данные в основной форме, но создавать отсортированные копии для частых запросов.
Ленивая сортировка: Откладывать сортировку до первого запроса, требующего порядка.
Когда избегать сортировки
Единичные операции: Если требуется одна операция поиска, линейный поиск может быть эффективнее.
Частые модификации: При постоянных добавлениях/удалениях поддержание отсортированного состояния требует дополнительных затрат.
Ограниченные ресурсы: На устройствах с ограниченной памятью in-place сортировка предпочтительнее, но может быть слишком дорогой по времени.
Выбор алгоритма сортировки
Критерии выбора:
Устойчивость: Нужна ли сохранение относительного порядка?
Память: Доступна ли дополнительная память O(n)?
Время: Важна ли гарантия O(n log n) в худшем случае?
Данные: Частично отсортированы ли данные?
#Java #для_новичков #beginner #algorithm #sorted
👍6
Что выведет код?
#Tasks
import java.util.*;
public class Task190126 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(5, 2, 9, 1, 5, 6);
Comparator<Integer> comparator = (a, b) -> {
if (a % 2 == b % 2) return 0;
return a % 2 == 0 ? -1 : 1;
};
Collections.sort(list, comparator);
System.out.println(list);
}
}
#Tasks
👍3
Варианты ответа:
Anonymous Quiz
28%
[2, 6, 5, 9, 1, 5]
28%
[5, 2, 9, 1, 5, 6]
22%
[1, 2, 5, 5, 6, 9]
22%
Исключение IllegalArgumentException
🤯3