Notes about Java 🌴
197 subscribers
41 photos
1 video
3 files
76 links
vk.com/notes_about_java
Научим программировать с нуля!
1. Видео на практике в коде
2. Краткие по времени
3. Очередной урок только на пройденном
4. Понятные аналогии
5. Можно скачать код занятий
@max_urusoff
Download Telegram
#immutablemap

ImmutableMap на самом деле полезная вещь и порой недооценена там где она должна быть.
Уверен, что значения в мапе будут меняться? На самом деле?

Может достаточно сделать вот так:
ImmutableMap<String, String> immutableMap = ImmutableMap.<String, String>builder()
.putAll(someMutableMap)
.put("Costa Rica", "North America")
.build();

В таком виде получается безопасная мапа с которой не страшно работать при отсутствии необходимости модификации, особенно если ее надо отдать наружу из класса.

Подробнее здесь:
https://www.baeldung.com/java-immutable-maps
👍5
#singular

Удобно пользоваться аннотацией @Singular от Lombok в билдерах @Builder.
Аннотация автоматически генерирует возможность подавать элементы коллекции в билдере в виде:
.table(sourceTable)
.table(targetTable)

Вместо оборачивания всех подаваемых полей через конструкцию из древних веков - Arrays.asList(sourceTable, targetTable).

https://www.baeldung.com/lombok-builder-singular
🤓1
#lombokvar

Когда ты знаешь контекст и тебе быстро нужно определённое поле под рукой, то Lombok var - то что надо.
Достаточно написать вот так как на картинке (указано стрелкой) и стринги готовы к  работе.

ВАЖНО!
С этими var надо быть внимательным:
- при множестве таких полей не перепутать при работе
- не стоит давать малопонятные имена var полям
- это lazy тип, который получает себя от начинки.

https://www.baeldung.com/java-lombok-val-var
👌1
#cachedthreadpool

Важно контролировать кол-во потоков (thread) и задач (task) в работающем пуле (thread pool), в противном случае многопоточка может только навредить работе приложения.
Это связано с тем, что потоки и задачи в очереди кушают ресурсы (память и процессор).
Особенно это касается Cached Thread Pool.
В этом типе пула очередь не может хранить задачи и создаёт новый поток если все заняты.
Так же этот тип пула не рекомендуется для I/O задач ВВОДА-ВЫВОДА.
Он подходит для ограниченного кол-ва задач и маленьких по времени выполнения.

👉 Почитать здесь:
https://www.baeldung.com/java-executors-cached-fixed-threadpool

https://javarush.com/quests/lectures/jru.module2.lecture23
👍1
#agile

Работаю в аджайле с 2017 года.
И хочется здесь отметить пару моментов из реального опыта глазами разработчика.
Возможно пригодится.

В одном из проектов за нормально описанную архитектурную документацию сервиса меня уволили из-за того, что я хорошо её прорисовал, а надо было вместо этого делать быстро и ТЯП-ЛЯП, так как заказчик уже хочет по другому.
- "Главное вернеуровневую часть архитектуры нарисуй, чтобы что-то показать заказчику".
Тех. директор поддержал меня и хотел оставить, но ситуация ему не позволяла.

В текущем проекте я вижу как аджайл пытается быть натянутым на сложный проект backend происхождения и эта методология приводит к некачественной реализации.

Сформировалось мнение, что аджайл возможно будет полезен для сайта типа wildberries (frontend часть) потому, что:
1. Сайт уже кто-то нормально сделал и он работал ещё до мыслей об аджайле.
2. Пользователи (бизнес) могут конструктивно оценить фичи уже работающего сайта и их стоит учитывать в технической реализации.

Во всех остальных кейсах аджайл будет провоцировать на быстрый поиск ПОЛУ-СЫРОГО или пилотного функционала (возможно и с аутсорс сострудниками), его быструю адаптацию и доработку.

А настоящему Java разработчику важно:
- интересный стек с задачами
- участие с тем, чтобы то что написано проработало адекватное время и не было выброшено в связи со стихийными изменениями архитектуры
- хорошие ТЗ и ответственность сотрудников за свои области

Так что фокусируемся на качестве кода проекта и интересных темах!

Статья для почитать ниже
https://habr.com/ru/post/580326/
👍2
#transient

Когда класс участвует в сериализации, но есть поля, которые не нужны после десериализации, то вешай модификатор TRANSIENT на поле.
Это позволит:
- не упасть лицом в грязь, записав пароль пользователей в класс
- ускорить выполнение, освободив сериализацию от мусора.

Бывает так, что сериализация достаётся по наследству от родительского класса.
Как раз такой пример представлен на скриншоте. Но мне в данном случае не надо, чтобы мои поля участвовали в сериализации. Более того, если убрать TRANSIENT, то на класс ругается система проверки качества кода SonarQube.

https://javarush.com/groups/posts/2898-chto-skrihvaet-modifikator-transient-v-java
🤔1
#desing #interface

Вот 👉 эти два куска дерева на заборе недалеко от моего офиса - это тот случай, когда в дизайне проекта нехватило интерфесов для новой реализации!
По сути это легаси, которое нельзя удалить, из-за того, что на этом что-то работает 😭

То есть в какой-то момент нужна новая реализация на интерфейсе, а вместо этого в проекте абстрактный класс с уже прописанной в нём реализацией.

https://stackoverflow.com/questions/22847942/java-interface-reference
👌3👍1
#sparkdate #sparktimestamp

Работа с типами дата и таймстамп заслуживает отдельного внимания в Apache Spark.
Особенно если есть джоины или фильтрация наборов данных по такого рода колонкам.
В таком случае все значения надо СТРОГО приводить к одному формату!
Иначе плакали наши данные и кино 🎥 показывать не будут.

На скриншоте наглядно показан пример взятия первых 10 значений из полей при джоине у обоих сторон.

Например timestamp или string с типом date джоинить нельзя. Иногда спарк сам может справиться с конвертацией и выдрать дату из таймстампа, НО это риск, который может вылезти в самый неожиданный момент.

https://spark-school.ru/blogs/timestamp-functions/
👍4
#completablefuture

Хорошее видео с разбором overhead'а при асинхронном выполнении и результатами замеров.

Мне понравился момент, когда автор в начале говорит, что перед началом исследования сделал пост в соц. сети с вопросом о использовании CompletableFuture и главным отзывом было - "нихрена непонятно как пользоваться".

Так же на 13 минуте приводиться несколько вариантов завершения. Это и есть фото в этом посте.

От себя отмечу, что CompletableFuture цепочки это аналог Stream API в Java и нужно быть внимательным с методами. Какие-то из них блокирующие, а какие-то нет.

🎥 Видео:
https://youtu.be/W7iK74YA5NM

Примеры кода:
https://liakh-aliaksandr.medium.com/asynchronous-programming-in-java-with-completablefuture-47ab86458aab
🤔1
This media is not supported in your browser
VIEW IN TELEGRAM
#codereview

Видео 🎥 показывает что переживает разраб сделавший доработки и создавший Pull Request для код ревью! От души!

https://habr.com/ru/company/selectel/blog/660947/
😁1😢1
#sparkdataframe

Могу сказать, что основной класс Dataset в спарке - это полная дичь:
1. Отсутствуют какие-либо Java docs, чтобы хоть понять можно было - что на самом деле будет делать тот или иной метод.
2. Типы джоинов надо указывать стрингом, пример - "left". Если ошибёшься - сам виноват.
3. Имена параметров в методах вообще непонятны. Возникает ощущение, что компания авторов была не совсем трезвая и писали имена полей упрощённо - "other".

Но несмотря на проблемы, этот класс поставляется как основной для работы с Apache Hadoop.

На данный момент мне удалось написать свой класс обёртку где перечисленные и другие проблемы решены и сделаны нормальные методы. Возможно со временем после обкатки и реальных тестов я поделюсь этим решением через GitHub.

А пока вот описание:
https://www.baeldung.com/spark-dataframes
👍3
#javadoc

Пример кода в составе джавадока это не сложно.
Внутри фигурных скобок надо написать @code и далее описать как создать экземпляр класса и пользоваться методами.

https://www.baeldung.com/javadoc
👍3
#sparkcache #persist

Кэширование это тема.
Но перед тем как написать в коде .cache() надо взвесить - будет ли выхлоп с кэширования??

Стоит учесть, что это полезно ТОЛЬКО в том случае, когда есть многократное переиспользование одного и того же датафрейма!

Если как минимум 2 раза к КЭШИРОВАННОМУ датафрейму обращения не будет, то можно спокойно писать код и не занимайся этим кэшем.

Плюс отдельно надо сказать, что как правило оперативной памяти не хватает. Отсюда строгая рекомендация - если кэшировать, то только фильтрованный датафрейм! Например данные за сегодня или за интервал, но НЕ все данные гнать в память.

https://bigdataschool-ru.turbopages.org/turbo/bigdataschool.ru/s/blog/caching-in-spark-sql.html
👍3
#completionservice
#completablefuture

Отличный вопрос и пример кода асинхронной обработки taskов.
Надо сказать, что вопрос задан очень интересно🤔.

Ведь CompletionService предоставляет метод take() который может обрабатывать результат дальше по готовности без блокировки и ожидания потоков-соседей!

В данном случае CompletableFuture оказывается удобнее и богаче по набору методов для асинхронной обработки задач. Можно писать целые chainы логической последовательности действий.

Здесь кстати, чтобы разобраться в этом посте надо понимать что такое асинхронность вообще??

Вот видос от Luxsoft который поможет в этом разобраться!
https://youtu.be/yBF9VRiGkik


Ну и сама статья для примера:
https://stackoverflow.com/questions/63762096/completionservice-vs-completablefuture
👍4
#generics

Есть такие типы - дженерики называются. Ссылка для самообучения от javarush ниже.
Но сейчас не об этом.
Эта записка о том, что есть конвенция именования дженерик параметров ОДНОЙ ЗАГЛАВНОЙ БУКВОЙ.

Так вот, проблема в том, что на практике когда тебе нужны несколько параметров да ещё и с одинаковыми первыми буквами классов - это похоже на издевательство:
1. Не понятно по одной букве что за тип стоит за буквой.
2. Можно начать танцевать и добавить цифру к букве, НО читаемость это не сделает.

Поэтому удобнее делать дженерик типы по заглавным буквам интерфейса или класса.

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

Оказывается я не одинок в этой мысли, вот ссылка на беседу:
https://stackoverflow.com/a/33394836

Что такое дженерик типы:
https://javarush.com/groups/posts/2004-teorija-dzhenerikov-v-java-ili-gde-na-praktike-stavitjh-skobki
👍1
#ssd
#linuxmint

Мой жёсткий диск на ноутбуке сгорел ещё во время первой волны ковида при вынужденной работе из дома.
Добрался до замены - взял SSD Kingston вместо обычного для ускорения.
Ощущения от SSD хорошие - установка новой ОС Linux Mint заняла всего около 10 минут. Под разработку и обучение самое то - рекомендую!

Качнуть актуальную версию можно по ссылке:

https://linuxmint.com/download.php
👍2🔥2
#asyncprofiler

Профилирование помогает найти утечки и проблемные зоны в коде по расходу процессора и памяти.
Итак жмем на методе с тестом в контекстном меню "Profile with Async Profiler" и запускаем.
Дальше во всей каше построенного графика можно не пытаться разобраться, а сразу в поиске вписать имя метода, который и надо проверить на корректность ожидаемой работы и поеданию ресурсов.

Бывает такое, что IDEA не может найти целевой метод - надо еще точнее написать тест, без ничего лишнего, а только на нужный метод.

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

Более подробно о том, как работать с результатами профилирования написано здесь:
https://www.jetbrains.com/help/idea/read-the-profiling-report.html
👍1
#asynchronous

Классная статья для понимания разницы между многопоточным и асинхронным выполнением.
А в самом деле есть ещё третий вид - это вкусный компот из обоих вместе!
Именно таким путём и развивается Java.

От многопоточного до асинхронно-многопоточного.

Хронология по функционалу:
ForkJoinPool->CompletableFuture->ReactiveStreams!

https://www.baeldung.com/cs/async-vs-multi-threading
👍1
#springdatajpa

На днях в коде проекта увидел @Entity класс помеченный @Data аннотацией от Lombok.
Благо у меня в IDEA подключён плагин JPA buddy.
А то так можно и не заметить.
Он сразу подсветил, что эта аннотация не применяется для entity сущностей, так как генерируемый код нарушает концепцию JPA и помешает нормально работать.
В том числе возможны и проблемы с производительностью.

При работе с JPA помните следующие правила:

1.Избегайте использования аннотаций @EqualsAndHashCode и @Data с JPA сущностями;

2.Исключайте ленивые поля при использовании аннотации @ToString;

3.Не забывайте добавлять аннотацию @NoArgsConstructor к сущностям помеченным аннотациями @Builder или @AllArgsConstructor. Это нужно, чтобы спринг мог работать с сущностью как он этого и ждёт - с конструктором без аргументов.

https://habr.com/ru/companies/haulmont/articles/564682/
👍1
#пасха

Христос Воскресе! Светлое Христово Воскресенье!
🥳
Удивительно, но это факт.
Я смотрел фильм научный где группа учёных физиков исследовали плащаницу в которую был завернут Иисус. По результатам они сказали, что для того чтобы так прожечь материал прям точно по контуру тела умершего, должно было быть подано напряжение около 600 Вольт. К сожалению это было по телевизору, может и найду ссылку. Но передача была.
В общем с ПАСХОЙ!