Библиотека джависта | Java, Spring, Maven, Hibernate
24.9K subscribers
1.86K photos
38 videos
42 files
2.64K links
Все самое полезное для Java-разработчика в одном канале.

Список наших каналов: https://yangx.top/proglibrary/9197

Обратная связь: @proglibrary_feedback_bot

По рекламе: @proglib_adv

РКН: https://gosuslugi.ru/snet/67a5bbda1b17b35b6c1a55c4
加入频道
#дайджест #Javadevjob

Вакансии Java разработчиков уровня Junior

▪️ Junior Java Developer
Удалёнка / Офис (Москва, Новосибирск), Динамика
Подробнее

▪️ Backend Developer (JAVA)
Гибрид (Москва), СберЗдоровье
Подробнее

Вакансии Java разработчиков уровня Middle


▪️ Java-разработчик в Систему фрод-мониторинга
Офис (Москва) / Удалёнка, Мир Plat.Form (НСПК)
Подробнее

▪️ Java разработчик (Middle)
Офис (Москва) / Удалёнка, СОГАЗ
Подробнее

Вакансии Java разработчиков уровня Senior

▪️ Java разработчик
Гибрид (Москва) / Удалёнка, СИГМА
Подробнее

▪️ Java/Kotlin Backend Developer
Офис (Москва, Санкт-Петербург) / Удалёнка, Okko
Подробнее

Понравились вакансии?
❤️ — да
🤔 — нет
November 24, 2024
💡 Глубокий взгляд на реализацию Arrays.sort()

А вы задумывались, что скрывается под капотом Arrays.sort()? Быстрая сортировка? Пузырёк? Или, может, что-то ещё?

На самом деле, Arrays.sort() – это больше, чем просто сортировка. Этот метод использует адаптивные алгоритмы и оптимизации, которые подстраиваются под тип данных и размер массива. А главное – в его реализации предусмотрена защита от худших случаев, таких как неудачное распределение данных, чтобы всегда обеспечивать стабильную производительность.

1️⃣ Примитивы: Dual-Pivot Quicksort

Для массивов примитивных типов (int, double и т.д.) используется Dual-Pivot Quicksort. Он выбирает два опорных элемента, которые делят массив на три части: элементы меньше первого опорного, между опорными и больше второго, с последующей рекурсивной сортировкой каждой части.

🔍 Как это выглядит:

if (arr[left] > arr[right]) {
swap(arr, left, right);
}
int pivot1 = arr[left];
int pivot2 = arr[right];

int i = left + 1, lt = left + 1, gt = right - 1;
while (i <= gt) {
if (arr[i] < pivot1) {
swap(arr, i++, lt++); // Элементы меньше первого опорного
} else if (arr[i] > pivot2) {
swap(arr, i, gt--); // Элементы больше второго опорного
} else {
i++; // Элементы между опорными
}
}
swap(arr, left, --lt);
swap(arr, right, ++gt);


📌 Почему это эффективно?

- Использование двух опорных элементов снижает глубину рекурсии.
- Разбиение на три части позволяет сбалансировать массив быстрее, чем в классическом Quicksort.
- Работает in-place, избегая лишних выделений.
- Даже на отсортированных или случайных данных Dual-Pivot Quicksort показывает стабильную производительность.

2️⃣ Ссылочные типы: Timsort

Если вы сортируете объекты (String, Integer и т.д.), то под капотом работает Timsort – гибридный алгоритм, который сочетает Merge Sort и Insertion Sort. Он адаптивно обрабатывает массивы, находя уже отсортированные последовательности (run'ы) и минимизируя количество операций для их слияния.

🔍 Как это выглядит:

int runLen = 32; // Минимальная длина run
for (int i = 0; i < array.length; i += runLen) {
insertionSort(array, i, Math.min((i + runLen - 1), array.length - 1));
}

while (stackSize > 1) {
if (runLen[stackSize - 2] <= runLen[stackSize - 1]) {
mergeRun(stackSize - 2, stackSize - 1); // Слияние соседних run'ов
}
}


📌 Почему это эффективно?

- Timsort автоматически находит уже отсортированные подмассивы, уменьшая объём работы.
- Работает с заранее выделенными буферами для быстрого слияния подмассивов.
- Сохраняет порядок равных элементов, что важно для многих задач.
- Производительность близка к O(n) на частично отсортированных данных.

3️⃣ Небольшие массивы: Insertion Sort

Для массивов с небольшим количеством элементов (до 32) используется Insertion Sort (сортировка вставками). Он работает, проходя по массиву и вставляя каждый элемент на своё место в уже отсортированной части, сдвигая элементы, которые больше текущего, вправо. Этот алгоритм применяется, так как на малых объёмах данных он оказывается быстрее более сложных методов благодаря низким накладным расходам и простоте реализации.

🔍 Как это выглядит:

for (int i = left + 1; i <= right; i++) {
int key = array[i];
int j = i - 1;
while (j >= left && array[j] > key) {
array[j + 1] = array[j];
j--;
}
array[j + 1] = key;
}


📌 Почему это эффективно?

- Алгоритм не требует дополнительной памяти и выполняется in-place.
- Сложность O(n^2) на больших данных компенсируется эффективностью на длине до 32 элементов.
- Использует уже загруженные данные в кэше процессора, что ускоряет доступ к памяти.
Please open Telegram to view this post
VIEW IN TELEGRAM
November 24, 2024
☄️ Проверь себя

Хочешь узнать, насколько ты прокачан в разработке? Тест для айтишников, чтобы проверить знания. Отличный способ отвлечься и сравнить результаты с друзьями!

👉 Пройти
Please open Telegram to view this post
VIEW IN TELEGRAM
November 25, 2024
💡 Как избежать катастрофы при переходе на PostgreSQL: руководство по спасению базы данных

Переход на PostgreSQL — это не просто замена одного инструмента другим. Неправильный подход может привести к потере данных, снижению производительности и длительным простоям. Особенно это касается хранимых процедур: различия между PL/pgSQL и языками, такими как PL/SQL или T-SQL, могут вызывать ошибки, которые сложно обнаружить заранее.

Если вы хотите узнать, как избежать этих проблем, правильно спланировать переход и не потерять производительность, ознакомьтесь с важными советами и готовыми решениями, которые сделают миграцию безопасной и эффективной. 🚀

🔗 Читать статью
🔗 Зеркало
Please open Telegram to view this post
VIEW IN TELEGRAM
November 25, 2024
November 25, 2024
🖥 Топ-10 советов по настройке PostgreSQL

Если вы работаете с PostgreSQL в условиях высокой нагрузки или больших объемов данных, оптимизация становится ключевым элементом успеха.

Вот несколько советов, которые помогут повысить производительность вашей базы данных:

👉 Переходите по
ссылке
Please open Telegram to view this post
VIEW IN TELEGRAM
November 26, 2024
🔒 Pessimistic vs Optimistic Locking

🔵 Pessimistic Locking

- Запись недоступна для других потоков до тех пор, пока текущий поток не закончит работу с ней.
- Даже чтение данных другими потоками невозможно, пока лок не снят.
- Пример: EntityManager.lock(entity, LockModeType.PESSIMISTIC_WRITE) в JPA.
- Минусы: снижает производительность при высоком уровне конкурентного доступа.
- Когда применять: при критической необходимости точности данных.

🔵 Optimistic Locking

- Не блокирует данные при чтении, но проверяет версию записи при сохранении.
- Пример: аннотация @Version в JPA (колонка для хранения версии).
- Если версия изменена другим потоком, выбрасывается OptimisticLockException.
- Минусы: требует обработки конфликтов.
- Когда применять: при большом количестве чтений и низкой вероятности конфликтов.

💬 Какой подход вы чаще используете в своих проектах?
Please open Telegram to view this post
VIEW IN TELEGRAM
November 27, 2024
November 27, 2024
This media is not supported in your browser
VIEW IN TELEGRAM
November 28, 2024
🏢📊 Как сократить расходы на инфраструктуру в 20 раз: опыт внедрения мультитенантной архитектуры

Снизить затраты на инфраструктуру в десятки раз — не фантастика, а реальность. Мультитенантная архитектура помогает не только экономить деньги, но и упрощает подключение новых клиентов, масштабирование и обслуживание системы. Такой подход значительно облегчает работу и открывает новые возможности для роста.

Хотите узнать, как правильно её внедрить, избежать типичных ошибок и достичь впечатляющих результатов? Ознакомьтесь с реальным опытом, который вдохновит на изменения. 🍹

🔗 Читать статью
🔗 Зеркало
Please open Telegram to view this post
VIEW IN TELEGRAM
November 28, 2024
November 28, 2024
Что такое GraphQL?

GraphQL — это язык запросов и среда выполнения для API. Его основная цель — предоставить клиентам возможность запрашивать только те данные, которые действительно нужны, и делать это гибко, без избыточности. Это мощная альтернатива REST API, которая делает взаимодействие между клиентом и сервером более эффективным и удобным.

❗️ Ключевые особенности GraphQL

🔵 Запросы по потребности

Клиент сам определяет, какие данные ему нужны, задавая структуру запроса. Сервер возвращает только запрошенные поля, ничего лишнего.

Пример:

query {
user(id: "1") {
name
email
}
}

Ответ:
{
"data": {
"user": {
"name": "John Doe",
"email": "john.doe@example.com"
}
}
}


🔵 Единая точка входа (Single Endpoint)

В отличие от REST, где для разных операций используются разные URL (например, /users, /posts), в GraphQL всё взаимодействие происходит через единый эндпоинт, например, /graphql.

🔵 Гибкость и вложенные запросы

Можно запрашивать сложные связанные данные в одном запросе.

Пример:

query {
user(id: "1") {
name
posts {
title
comments {
text
}
}
}
}

Ответ:
{
"data": {
"user": {
"name": "John Doe",
"posts": [
{
"title": "My First Post",
"comments": [
{ "text": "Great post!" },
{ "text": "Very helpful, thanks!" }
]
}
]
}
}
}


🔵 Строгая типизация

GraphQL API имеет чётко описанную схему данных. Это позволяет клиентам знать, какие поля доступны, и снижает вероятность ошибок.

Пример схемы:

type User {
id: ID!
name: String!
email: String!
posts: [Post]
}

type Post {
id: ID!
title: String!
comments: [Comment]
}

type Comment {
id: ID!
text: String!
}


🔵 Поддержка мутаций

GraphQL поддерживает не только чтение данных, но и их изменение через мутации.

Пример мутации:

mutation {
createUser(input: { name: "Jane", email: "jane@example.com" }) {
id
name
email
}
}

Ответ:
{
"data": {
"createUser": {
"id": "2",
"name": "Jane",
"email": "jane@example.com"
}
}
}


🔵 Реактивность через подписки (Subscriptions)

Позволяет клиенту получать обновления в реальном времени. Это особенно полезно для чатов, уведомлений и других событий.

Пример:

subscription {
messageAdded {
id
text
}
}


🔼 Преимущества GraphQL

- Экономия трафика: Возвращает только запрошенные данные.
- Меньше запросов: Вложенные данные можно получить за один запрос.
- Документация встроена в схему: Инструменты вроде GraphiQL позволяют изучать API прямо в процессе разработки.
- Гибкость для клиентов: Клиент управляет структурой ответа.

🔽 Недостатки GraphQL

- Требуется больше усилий для проектирования схемы и серверной логики.
- Возможны слишком сложные запросы, которые могут перегружать сервер.
- Сложнее настроить кеширование.
Please open Telegram to view this post
VIEW IN TELEGRAM
November 29, 2024
November 29, 2024
👀 Задачи с собеседований: Проверка, является ли бинарное дерево деревом поиска (middle)

— Как определить, является ли заданное бинарное дерево деревом поиска (BST)?

💡 Ключевые моменты:

- Бинарное дерево поиска (BST) — это бинарное дерево, в котором для каждого узла все значения в левом поддереве меньше значения узла, а все значения в правом поддереве больше.
- Для проверки можно использовать рекурсивный подход с отслеживанием допустимых диапазонов значений для каждого узла.
- Как изменить реализацию для работы с любыми типами данных в узлах дерева?

Реализация с числами в узлах на картинке 👆🏻
Please open Telegram to view this post
VIEW IN TELEGRAM
November 30, 2024
🕯 Паттерн Фасад (Facade)

Фасад — это структурный паттерн, который предоставляет унифицированный интерфейс для работы с набором сложных подсистем. Он скрывает сложность системы и упрощает взаимодействие с ней, предоставляя более простой и понятный API для клиента.

Использование:

🔹 Когда система состоит из множества классов, и нужно упростить доступ к её функционалу.
🔹 Когда нужно предоставить клиенту единый интерфейс для работы с несколькими подсистемами.
🔹 Когда необходимо уменьшить зависимость между клиентом и сложной системой, скрыв внутренние детали реализации.

Преимущества:

1️⃣ Упрощает взаимодействие с комплексной системой, предоставляя удобный интерфейс.
2️⃣ Снижает зависимость клиента от конкретных классов подсистем, облегчая поддержку и тестирование.
3️⃣ Уменьшает количество точек взаимодействия с системой, что помогает избежать ошибок и повысить удобство работы.

Недостатки:

1️⃣ Может скрывать избыточную функциональность, ограничивая возможности системы.
2️⃣ Увеличивает количество кода за счёт добавления нового фасадного класса.
3️⃣ Если фасад слишком абстрактен, может стать сложным для понимания и поддержки.

📌 Паттерн Фасад полезен, когда нужно объединить несколько подсистем под один общий интерфейс, делая систему более удобной и простой для использования. Например, при работе с библиотеками, требующими сложной настройки, или в крупных проектах, где взаимодействие с множеством компонентов может стать запутанным. Фасад помогает улучшить архитектуру и повысить удобство работы с системой.
Please open Telegram to view this post
VIEW IN TELEGRAM
December 1, 2024
December 2, 2024
#дайджест #Javadevjob

Вакансии Java разработчиков уровня Junior

▪️ Junior Java Developer
Гибрид (Санкт-Петербург), Just AI
Подробнее

▪️ Junior Java Developer
Офис (Москва) / Удалёнка, Trend Soft
Подробнее

Вакансии Java разработчиков уровня Middle

▪️ Java-разработчик
Офис (Москва), Газпромбанк
Подробнее

▪️ Java Developer (middle+)
Удалёнка, ОЦРВ
Подробнее

Вакансии Java разработчиков уровня Senior

▪️ Java-разработчик (проект СЭД)
Офис (Москва), Гринатом
Подробнее

▪️ Java Developer + ELK
Удалёнка, Hoff Tech
Подробнее

Понравились вакансии?
❤️ — да
🤔 — нет
December 2, 2024