Совет по Java: предпочитай инъекцию через конструктор, а не инъекцию в поля.
👉 Java Portal
Инъекция в поле:
@Component
public class UserController {
@Autowired
private Logger logger;
public void createUser(String username) {
...
}
}
// Сложнее тестировать изолированно.
Инъекция через конструктор:
...
private final Logger logger;
@Autowired
public UserController(Logger logger) {
this.logger = logger;
}
...
// Проще создавать экземпляр для unit-тестов
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Топ оконных функций, которые использует каждый data-инженер
1. ROW_NUMBER()
ROW_NUMBER() позволяет пронумеровать строки в рамках группы, что сильно упрощает дедупликацию. Нужно взять последнюю запись по клиенту или первое событие в сессии — решается чисто и без костылей.
2. DENSE_RANK()
Если делаешь лидерборды или бизнес-уровни, эта функция всплывает почти сразу. Она группирует одинаковые значения без пропусков в нумерации — рейтинги получаются понятными даже для нетехнических стейкхолдеров.
3. LAG() / LEAD()
Используются, чтобы посмотреть на предыдущее или следующее значение. Идеально подходит для сравнения сегодняшних продаж со вчерашними или поиска изменений между событиями.
4. SUM() OVER()
Так делаются накопительные суммы без развала запроса. SUM() OVER() позволяет сохранить детализацию по строкам и при этом добавить кумулятивные итоги. Очень удобно в финансовых и событийных пайплайнах.
5. FIRST_VALUE() / LAST_VALUE()
Нужны, когда важен контекст. Помогают взять первое или последнее значение внутри партиции — критично для временной аналитики, например при сравнении стартовых и финальных значений или расчёте метрик жизненного цикла.
👉 Java Portal
1. ROW_NUMBER()
ROW_NUMBER() позволяет пронумеровать строки в рамках группы, что сильно упрощает дедупликацию. Нужно взять последнюю запись по клиенту или первое событие в сессии — решается чисто и без костылей.
2. DENSE_RANK()
Если делаешь лидерборды или бизнес-уровни, эта функция всплывает почти сразу. Она группирует одинаковые значения без пропусков в нумерации — рейтинги получаются понятными даже для нетехнических стейкхолдеров.
3. LAG() / LEAD()
Используются, чтобы посмотреть на предыдущее или следующее значение. Идеально подходит для сравнения сегодняшних продаж со вчерашними или поиска изменений между событиями.
4. SUM() OVER()
Так делаются накопительные суммы без развала запроса. SUM() OVER() позволяет сохранить детализацию по строкам и при этом добавить кумулятивные итоги. Очень удобно в финансовых и событийных пайплайнах.
5. FIRST_VALUE() / LAST_VALUE()
Нужны, когда важен контекст. Помогают взять первое или последнее значение внутри партиции — критично для временной аналитики, например при сравнении стартовых и финальных значений или расчёте метрик жизненного цикла.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍2😁2
Spring Boot: если в коде используется RestTemplate, тесты можно писать, подменяя внешние HTTP-вызовы с помощью MockRestServiceServer.
✅ MockRestServiceServer работает за счет перехвата HTTP-запросов.
Дан сервис, который дергает внешний API:
Тест можно реализовать так:
👉 Java Portal
Дан сервис, который дергает внешний API:
@Service
public class ProductService {
private final RestTemplate restTemplate;
public ProductService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public String getProductName(long id) {
Product product = restTemplate.getForObject(
"https://remoteapi.com/products/{id}",
Product.class,
id
);
return product.getName();
}
}
Тест можно реализовать так:
@SpringBootTest
class ProductServiceTest {
@Autowired
private RestTemplate restTemplate;
@Autowired
private ProductService productService;
private MockRestServiceServer mockServer;
@BeforeEach
void setup() {
mockServer = MockRestServiceServer.createServer(restTemplate);
}
@Test
void shouldReturnProductWhenExternalApiCalled() {
// Arrange
mockServer.expect(requestTo("https://remoteapi.com/products/1"))
.andExpect(method(HttpMethod.GET))
.andRespond(withSuccess(
"{\"id\":1,\"name\":\"USB stick\"}",
MediaType.APPLICATION_JSON
));
// Act
ProductDto product = productService.getProduct(1L);
// Assert
assertThat(product.getName()).isEqualTo("USB stick");
mockServer.verify();
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤4🔥2😁2
Нашли офигенный способ выучить PostgreSQL в браузере : crunchydata
PostgreSQL-песочница с практическими уроками SQL, транзакциям, индексам, PostGIS и не только
🛌
👉 Java Portal
PostgreSQL-песочница с практическими уроками SQL, транзакциям, индексам, PostGIS и не только
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤2😁1
Java: не пихай бизнес-логику в Stream.peek(). Используй его только для отладки.
Смысл простой: peek() предназначен для легкого дебага и просмотра потока, а не для вычислений или побочных эффектов.
Используй только для легкой отладки
Пример: просмотр (инспекция) потока пайплайна
👉 Java Portal
Смысл простой: peek() предназначен для легкого дебага и просмотра потока, а не для вычислений или побочных эффектов.
Используй только для легкой отладки
Пример: просмотр (инспекция) потока пайплайна
list.stream()
.filter(x -> x > 10)
.peek(x -> System.out.println("Filter: " + x))
.map(x -> x * 2)
.peek(x -> System.out.println("Map: " + x))
.toList();
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤4
Выбирай направление:
Промпты, обучение, шпаргалки и полезные ресурсы на каждую тему!
Please open Telegram to view this post
VIEW IN TELEGRAM
🌚2🔥1
Под капотом многопоточной синхронизации в Java: как потоки договариваются через Mark Word
Синхронизация в Java часто воспринимается как простая языковая конструкция — достаточно использовать ключевое слово synchronized, и код начинает «просто работать».
На практике же на уровне JVM происходит цепочка событий, которую можно проследить до Mark Word — восьмибайтового служебного поля заголовка каждого Java-объекта.
Современные JVM (HotSpot, OpenJ9, GraalVM) не используют фиксированную модель блокировок. Вместо этого они динамически выбирают стратегию синхронизации, исходя из реального поведения потоков и истории использования объекта.
Эта статья предназначена для Java‑разработчиков, которые уже знакомы с многопоточностью и synchronized, но хотят разобраться, как именно JVM управляет блокировками, какие состояния проходит объект и какую роль в этом играет Mark Word.
👉 Java Portal
Синхронизация в Java часто воспринимается как простая языковая конструкция — достаточно использовать ключевое слово synchronized, и код начинает «просто работать».
На практике же на уровне JVM происходит цепочка событий, которую можно проследить до Mark Word — восьмибайтового служебного поля заголовка каждого Java-объекта.
Современные JVM (HotSpot, OpenJ9, GraalVM) не используют фиксированную модель блокировок. Вместо этого они динамически выбирают стратегию синхронизации, исходя из реального поведения потоков и истории использования объекта.
Эта статья предназначена для Java‑разработчиков, которые уже знакомы с многопоточностью и synchronized, но хотят разобраться, как именно JVM управляет блокировками, какие состояния проходит объект и какую роль в этом играет Mark Word.
Please open Telegram to view this post
VIEW IN TELEGRAM
Хабр
Под капотом многопоточной синхронизации в Java: как потоки договариваются через Mark Word
Синхронизация в Java часто воспринимается как простая языковая конструкция — достаточно использовать ключевое слово synchronized , и код начинает «просто работать». На практике же на уровне JVM...
🔥3
Java подсказка : не злоупотребляй наследованием. Когда можно — лучше делегируй. Наследование создаёт сильную связку, и это может выстрелить в ногу, если базовый класс изменится.
Предположим, у нас есть такой класс:
и Car наследуется от Engine:
Наследование выражает отношение is, но автомобиль на самом деле не является двигателем, он имеет двигатель. Перепишем через делегацию:
Таким образом эти два класса развязаны, и отношение превращается в has.
👉 Java Portal
Предположим, у нас есть такой класс:
class Engine {
void start() {
}
}и Car наследуется от Engine:
class Car extends Engine {
void drive() {
start();
}
}Наследование выражает отношение is, но автомобиль на самом деле не является двигателем, он имеет двигатель. Перепишем через делегацию:
class Car {
private Engine engine;
Car(Engine engine) {
this.engine = engine;
}
void drive() {
engine.start();
}
}Таким образом эти два класса развязаны, и отношение превращается в has.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤1
А может ли Java гонять TensorFlow без JNI и без Python?
Автор взял Java 25 + FFM и протащил это всё до C-шного TensorFlow API, собрав рабочий REST-сервис на macOS.
Результат: предсказуемая память, нативная производительность и максимально скучная (в хорошем смысле) архитектура.
Ломали когда-нибудь Quarkus-эндпоинт просто тем, что решили залогировать request body?
В этом гайде показывают, как безопасно аудировать, чистить и трассировать HTTP-запросы через request filters в Quarkus, не блокируя обработку и не убивая API.
Практично и можно почти копипастить.
👉 Java Portal
Автор взял Java 25 + FFM и протащил это всё до C-шного TensorFlow API, собрав рабочий REST-сервис на macOS.
Результат: предсказуемая память, нативная производительность и максимально скучная (в хорошем смысле) архитектура.
Ломали когда-нибудь Quarkus-эндпоинт просто тем, что решили залогировать request body?
В этом гайде показывают, как безопасно аудировать, чистить и трассировать HTTP-запросы через request filters в Quarkus, не блокируя обработку и не убивая API.
Практично и можно почти копипастить.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👀3
Java: не вешай логику в Stream.peek(), используй его только для отладки.
Используй его для легкой отладки
Пример: инспекция потока пайплайна
👉 Java Portal
Используй его для легкой отладки
Пример: инспекция потока пайплайна
list.stream()
.filter(x -> x > 10)
.peek(x -> System.out.println("Filter: " + x))
.map(x -> x * 2)
.peek(x -> System.out.println("Map: " + x))
.toList();
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔3
Spring Boot. Чтобы Jackson создавал объекты из JSON явно и предсказуемо, можно использовать аннотацию
Каждый параметр явно биндится.
Определяем конструктор с
👉 Java Portal
@JsonCreatorКаждый параметр явно биндится.
Определяем конструктор с
@JsonCreator:class User {
public final String username;
public final int age;
@JsonCreator
public User(
@JsonProperty("username") String username,
@JsonProperty("age") int age
) {
this.username = username;
this.age = age;
}
}Please open Telegram to view this post
VIEW IN TELEGRAM
❤11
Многопоточность позволяет писать так, чтобы несколько задач выполнялись параллельно внутри одного приложения.
Чтобы использовать многопоточность (то есть писать многопоточный код), нужен класс java.lang.Thread.
Стадии жизненного цикла потока:
• New: Новый поток начинает жизнь в состоянии new. Он остается там, пока программа не запустит поток.
• Runnable: После запуска новый поток становится runnable. В этом состоянии считается, что поток выполняет свою работу.
• Waiting: Иногда поток переходит в waiting, когда ему нужно дождаться выполнения задачи другим потоком.
• Timed Waiting: Поток из runnable может перейти в timed waiting на определенный промежуток времени. После истечения этого времени он снова возвращается в runnable.
• Terminated: Поток попадает в terminated после завершения задачи или принудительного завершения.
Приоритеты потоков:
Каждый Java-поток имеет приоритет, который помогает ОС решать порядок планирования потоков.
• MIN_PRIORITY (константа 1)
• NORM_PRIORITY (константа 5) (приоритет по умолчанию)
• MAX_PRIORITY (константа 10)
Базовые способы создать поток в Java:
• Реализовать интерфейс Runnable
• Наследоваться от Thread
Методы потоков:
• public void start()
Запускает поток в отдельном пути выполнения и затем вызывает run() у этого объекта Thread.
• public void run()
Если объект Thread был создан с отдельным Runnable, то run() будет вызван на этом Runnable.
• public final void setPriority(int priority)
Устанавливает приоритет потока. Возможные значения от 1 до 10.
• public void interrupt()
Прерывает поток, заставляя продолжить выполнение, даже если он был заблокирован.
• public final boolean isAlive()
Возвращает true, если поток "жив", то есть после старта и до завершения.
Это были базовые вещи. Пост длинный, но надеюсь, что что-то новое унес с собой.
👉 Java Portal
Чтобы использовать многопоточность (то есть писать многопоточный код), нужен класс java.lang.Thread.
Стадии жизненного цикла потока:
• New: Новый поток начинает жизнь в состоянии new. Он остается там, пока программа не запустит поток.
• Runnable: После запуска новый поток становится runnable. В этом состоянии считается, что поток выполняет свою работу.
• Waiting: Иногда поток переходит в waiting, когда ему нужно дождаться выполнения задачи другим потоком.
• Timed Waiting: Поток из runnable может перейти в timed waiting на определенный промежуток времени. После истечения этого времени он снова возвращается в runnable.
• Terminated: Поток попадает в terminated после завершения задачи или принудительного завершения.
Приоритеты потоков:
Каждый Java-поток имеет приоритет, который помогает ОС решать порядок планирования потоков.
• MIN_PRIORITY (константа 1)
• NORM_PRIORITY (константа 5) (приоритет по умолчанию)
• MAX_PRIORITY (константа 10)
Базовые способы создать поток в Java:
• Реализовать интерфейс Runnable
• Наследоваться от Thread
Методы потоков:
• public void start()
Запускает поток в отдельном пути выполнения и затем вызывает run() у этого объекта Thread.
• public void run()
Если объект Thread был создан с отдельным Runnable, то run() будет вызван на этом Runnable.
• public final void setPriority(int priority)
Устанавливает приоритет потока. Возможные значения от 1 до 10.
• public void interrupt()
Прерывает поток, заставляя продолжить выполнение, даже если он был заблокирован.
• public final boolean isAlive()
Возвращает true, если поток "жив", то есть после старта и до завершения.
Это были базовые вещи. Пост длинный, но надеюсь, что что-то новое унес с собой.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1