Java for Beginner
677 subscribers
546 photos
155 videos
12 files
836 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Варианты ответа:
Anonymous Quiz
14%
1
7%
2
48%
3
31%
Exception какой-то
#Mems. Небольшое несоответствие получилось.
Тут много нюансов...😂😂😂

https://t.me/Java_for_beginner_dev

#Mems
Collectors в Java

Collectors.collectingAndThen

Collectors.collectingAndThen – это особый коллектор, который добавляет финальное преобразование к результату другого коллектора. Это мощный инструмент для пост-обработки данных после сбора.

1. Базовая концепция

Сигнатура:
public static <T, A, R, RR> Collector<T, A, RR> collectingAndThen(
Collector<T, A, R> downstream,
Function<R, RR> finisher
)


Где:
downstream – основной коллектор (например, toList, groupingBy)
finisher – функция, применяемая к результату коллектора
RR – новый тип возвращаемого значения

2. Простые примеры

2.1. Создание неизменяемого списка
List<String> immutableList = stream
.collect(Collectors.collectingAndThen(
Collectors.toList(),
Collections::unmodifiableList
));


2.2. Получение первого элемента
String firstItem = stream
.collect(Collectors.collectingAndThen(
Collectors.toList(),
list -> list.isEmpty() ? null : list.get(0)
);


3. Комбинация с другими коллекторами


3.1. Группировка с неизменяемыми значениями
Map<String, List<Integer>> unmodifiableGroups = numbers.stream()
.collect(Collectors.collectingAndThen(
Collectors.groupingBy(
n -> n % 2 == 0 ? "even" : "odd"
),
Collections::unmodifiableMap
));


3.2. Подсчет с дополнительной проверкой

Long countOrZero = stream
.collect(Collectors.collectingAndThen(
Collectors.counting(),
c -> c > 100 ? c : 0L
));


4. Внутренняя реализация

Принцип работы:
Сначала выполняется основной коллектор (downstream)
Затем к его результату применяется finisher
Возвращается преобразованное значение


Псевдокод:
R intermediateResult = downstream.collect(stream);
RR finalResult = finisher.apply(intermediateResult);
return finalResult;


5. Практические применения


5.1. Безопасное извлечение Optional
Optional<String> lastElement = stream
.collect(Collectors.collectingAndThen(
Collectors.toList(),
list -> list.isEmpty()
? Optional.empty()
: Optional.of(list.get(list.size()-1))
);


5.2. Нормализация данных после группировки

Map<String, Set<String>> caseInsensitiveGroups = words.stream()
.collect(Collectors.collectingAndThen(
Collectors.groupingBy(
String::toLowerCase,
Collectors.toSet()
),
Collections::unmodifiableMap
));


6. Особенности и ограничения


Порядок выполнения:
Сначала полностью выполняется downstream-коллектор
Затем применяется finisher


Параллельные стримы:
Работает корректно, если finisher – thread-safe

Null-обработка:
Finisher должен сам обрабатывать null-значения

7. Производительность

Обычно добавляет незначительные накладные расходы:
5-10% к времени выполнения базового коллектора
В HotSpot часто инлайнится JIT-компилятором


#Java #Training #Medium #Collectors #partitioningBy
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Collectors в Java

Collectors.reducing


Collectors.reducing – это универсальный коллектор для выполнения операций свертки (reduction) над элементами потока. Он предоставляет более гибкую альтернативу встроенным операциям типа sum(), max() и min(), позволяя задавать собственную логику агрегации.

1. Три формы reducing
1.1. Базовая форма (с identity, mapper и операцией)
public static <T, U> Collector<T, ?, U> reducing(
U identity,
Function<? super T, ? extends U> mapper,
BinaryOperator<U> op
)


Параметры:
identity – начальное значение (аналог "нейтрального элемента")
mapper – функция преобразования элемента перед обработкой
op – операция для объединения двух значений


Пример (сумма длин строк):
List<String> words = List.of("Java", "Stream", "API");
int totalLength = words.stream()
.collect(Collectors.reducing(
0, // identity
String::length, // mapper
Integer::sum // op
));
// Результат: 11 (4 + 6 + 1)


1.2. Упрощенная форма (с identity и операцией)
public static <T> Collector<T, ?, T> reducing(
T identity,
BinaryOperator<T> op
)


Пример (конкатенация строк):
String concatenated = words.stream()
.collect(Collectors.reducing(
"", // identity
String::concat
));
// Результат: "JavaStreamAPI"


1.3. Минималистичная форма (только операция)

public static <T> Collector<T, ?, Optional<T>> reducing(
BinaryOperator<T> op
)


Пример (поиск максимального числа):
Optional<Integer> max = Stream.of(3, 1, 4)
.collect(Collectors.reducing(
Integer::max
));
// Результат: Optional[4]


2. Внутренняя реализация

Принцип работы:
Для каждого элемента применяет mapper (если указан)

Накопление результата через op:
// Псевдокод реализации
U result = identity;
for (T element : stream) {
result = op.apply(result, mapper.apply(element));
}
return result;
Для формы без identity использует Optional для обработки пустых потоков


3. Практические примеры
3.1. Сложная агрегация объектов
record Product(String name, double price) {}

List<Product> products = List.of(
new Product("Laptop", 999.99),
new Product("Phone", 599.99)
);

// Сумма цен продуктов с названием длиннее 4 символов
double total = products.stream()
.collect(Collectors.reducing(
0.0,
p -> p.name().length() > 4 ? p.price() : 0,
Double::sum
));


3.2. Комбинация с groupingBy
// Максимальная цена в каждой категории
Map<String, Optional<Product>> byCategory = products.stream()
.collect(Collectors.groupingBy(
Product::category,
Collectors.reducing((p1, p2) ->
p1.price() > p2.price() ? p1 : p2
));


3.3. Кастомная агрегация
// Пользовательская свертка для статистики
class Stats {
int count;
double sum;
// + конструкторы/методы
}

Stats stats = stream.collect(Collectors.reducing(
new Stats(0, 0.0),
num -> new Stats(1, num),
(s1, s2) -> new Stats(
s1.count + s2.count,
s1.sum + s2.sum
)
));


4. Ограничения и нюансы
Параллельные стримы:
Требует ассоциативности операции ((a op b) op c == a op (b op c))
Пример ассоциативных операций: сложение, умножение, min/max
Неассоциативные: вычитание, деление


Null-значения:
identity не может быть null
Операция должна обрабатывать null, если mapper может его вернуть


Производительность:
Чуть медленнее специализированных коллекторов (summingInt и др.)
На 10-15% медленнее прямого reduce для примитивов


5. Альтернативы
Когда лучше использовать другие методы:

Для примитивов:
// Вместо:
.collect(reducing(0, Integer::sum))

// Лучше:
.mapToInt().sum()


Для стандартных операций:
// Вместо:
.collect(reducing(Integer::max))

// Лучше:
.max(Comparator.naturalOrder())


Для неизменяемых коллекций:
// Вместо:
.collect(reducing(Collections.emptyList(), customMerge))

// Лучше:
.collect(toUnmodifiableList())


#Java #Training #Medium #Collectors #reducing
Что выведет код?

import java.util.*;

public class Task010525 {
public static void main(String[] args) {
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
Iterator<String> it = list.iterator();
list.add("D");

System.out.println(it.next());
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
32%
A
18%
B
5%
C
45%
ConcurrentModificationException
Ну да, вот только джуну 40+, а сеньору 23... 😂

https://t.me/Java_for_beginner_dev

#Mems
Please open Telegram to view this post
VIEW IN TELEGRAM
Вопросы с собеседования 👩‍💻

Какой метод возвращает длину массива byte?
Anonymous Quiz
15%
getLength()
12%
count()
24%
size()
49%
length
Collectors в Java

Кастомные коллекторы и неизменяемые коллекции

1. Создание кастомных коллекторов

Коллектор реализует интерфейс Collector<T, A, R>, где:
T – тип элементов потока
A – тип аккумулятора (промежуточное хранилище)
R – тип результата


Компоненты коллектора:
Supplier<A> – создает контейнер для накопления
BiConsumer<A, T> – добавляет элемент в контейнер
BinaryOperator<A> – объединяет частичные результаты (для параллельных стримов)
Function<A, R> – преобразует аккумулятор в результат
Characteristics (опционально) – набор характеристик (CONCURRENT, UNORDERED, IDENTITY_FINISH)


Пример: Кастомный коллектор для объединения строк с разделителем
Collector<String, StringBuilder, String> joinStrings = Collector.of(
StringBuilder::new, // supplier
(sb, str) -> { // accumulator
if (!sb.isEmpty()) sb.append(", ");
sb.append(str);
},
(sb1, sb2) -> { // combiner (для параллельных стримов)
if (sb1.length() > 0 && sb2.length() > 0) {
sb1.append(", ");
}
return sb1.append(sb2);
},
StringBuilder::toString // finisher
);

String result = Stream.of("Java", "Kotlin", "Scala")
.collect(joinStrings);

// Результат: "Java, Kotlin, Scala"


2. Неизменяемые коллекции

Java 10+ предоставляет встроенные коллекторы для неизменяемых коллекций:

2.1. Стандартные неизменяемые коллекторы
List<String> unmodifiableList = stream.collect(Collectors.toUnmodifiableList());
Set<String> unmodifiableSet = stream.collect(Collectors.toUnmodifiableSet());
Map<String, Integer> unmodifiableMap = stream.collect(
Collectors.toUnmodifiableMap(
keyMapper,
valueMapper,
mergeFunction // для обработки дубликатов
)
);


2.2. Создание через collectingAndThen
List<String> immutable = stream
.collect(Collectors.collectingAndThen(
Collectors.toList(),
Collections::unmodifiableList
));


3. Комбинирование подходов

3.1. Неизменяемый кастомный коллектор
Collector<String, List<String>, List<String>> toImmutableList = Collector.of(
ArrayList::new, // supplier
List::add, // accumulator
(left, right) -> { // combiner
left.addAll(right);
return left;
},
Collections::unmodifiableList // finisher
);


3.2. Группировка с неизменяемыми значениями
Map<String, List<Integer>> immutableGroups = numbers.stream()
.collect(Collectors.collectingAndThen(
Collectors.groupingBy(
n -> n % 2 == 0 ? "even" : "odd"
),
Collections::unmodifiableMap
));


4. Особенности реализации


4.1. Параллельная обработка
Кастомные коллекторы должны иметь thread-safe аккумулятор или характеристику CONCURRENT
Combiner должен корректно объединять частичные результаты


4.2. Оптимизации
Для примитивов используйте специализированные коллекторы (summingInt, averagingDouble)
Избегайте boxing/unboxing в кастомных коллекторах


4.3. Обработка null
Встроенные неизменяемые коллекторы бросают NullPointerException при null-элементах

Решение:
.filter(Objects::nonNull)
.collect(toUnmodifiableList())


Когда создавать кастомные коллекторы:
✔️ Для сложной логики агрегации
✔️ Когда встроенные коллекторы не подходят
✔️ Для оптимизации производительности в специфичных сценариях


Когда использовать неизменяемые коллекции:
✔️ Для безопасного возврата результатов из методов
✔️ В многопоточных сценариях
✔️ Для защиты данных от модификации


#Java #Training #Medium #Collectors
Объектно-реляционное отображение (ORM - Object-Relational Mapping) (оглавление)

Объектно-реляционное отображение (ORM - Object-Relational Mapping)
EntityManager
Аннотация @Entity
Аннотация @Table
Аннотация @Id
Аннотация @GeneratedValue
Аннотация @Column
Аннотация @Transient
Аннотация @Enumerated
Аннотация @Temporal
Аннотация @Lob
Аннотация @Version
Аннотация @Access Аннотации @AttributeOverride и @AttributeOverrides
Аннотация @Embeddable
Аннотация @Embedded
Аннотация @Inheritance
Аннотации @DiscriminatorColumn и @DiscriminatorValue
Аннотация @MappedSuperclass
Аннотация @OneToOne
Аннотации @OneToMany и @ManyToOne
Аннотация @ManyToMany
Аннотация @JoinColumn
Аннотация @JoinTable
Аннотация @ElementCollection
Аннотация @OrderColumn
Аннотация @PrimaryKeyJoinColumn
Аннотация @SecondaryTable
Аннотации @NamedQuery и @NamedQueries
Аннотации @NamedNativeQuery и @NamedNativeQueries
Аннотации @Convert и @Converter
Аннотации @PrePersist и @PostPersist
Аннотации @PreUpdate и @PostUpdate
Аннотации @PreRemove и @PostRemove

Аннотации Spring Data JPA

Аннотация @Query
Аннотация @Modifying
Аннотация @Param
Аннотация @Transactional
Аннотация @EnableJpaRepositories
Аннотация @EntityGraph
Аннотация @Lock
Аннотация @Procedure
Аннотация @IdClass
Аннотация @MapsId
Аннотация @CreatedBy
Аннотация @CreatedDate
Аннотации @LastModifiedBy и @LastModifiedDate
Аннотация @Version
Аннотация @PersistenceContext
Аннотация @EnableJpaAuditing
Аннотация @EntityListeners
Аннотация @Projection

Hibernate

Аннотация @Any
Аннотация @BatchSize
Аннотации @Cache и @Cacheable
Аннотация @Cascade
Аннотация @ColumnTransformer
Аннотация @DynamicInsert
Аннотация @DynamicUpdate
Аннотация @Filter
Аннотация @Formula
Аннотация @Generated
Аннотация @Immutable
Аннотация @Index
Аннотация @LazyCollection
Аннотация @LazyToOne
Аннотация @Loader
Аннотация @ManyToAny
Аннотация @MetaValue
Аннотация @NaturalId
Аннотация @NotFound
Аннотация @OnDelete
Аннотация @TableGenerator
Аннотация @OptimisticLock

#Content