All streams
Search
Write a publication
Pull to refresh
632
0
Тагир Валеев @tagir_valeev

Программист

Send message
Объекту в данном случае вообще пофиг — его никто и никак не изменяет и уж точно объекту никто ничего не присваивает.

В принципе valery1707 всё правильно сказал, незачем повторяться. "Присвоить объекту что-то" означает что объект будет этим владеть, обладать, либо это станет свойством объекта. Можно присвоить значение переменной, здесь всё нормально: переменную как раз можно представлять как контейнер со значением, и значение является её свойством.


но зачем заниматься буквоедством?

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


большинство постов на Хабре пишутся для широкой публики, максимально просто и понятно.

Использование слов не в общепринятом значении не способствует простоте и понятности.

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


На восьмой вопрос мой ответ: не мучайте киску. Если вам нужен putIfAbsent, берите CopyOnWriteArraySet и радуйтесь. Если вы по несчастью застряли с synchronizedList, рефакторьте код, это в любом случае опасная фигня (например, стримы от неё небезопасны, я дописал это в документации). Если уж совсем припёрло, почитайте документацию, там написано, что надо использовать в качестве монитора для синхронизации дополнительных операций. Помнить это наизусть необязательно. Про synchronizedList надо помнить одну вещь: что его лучше избегать и использовать крайне осторожно.


На девятый вопрос мой ответ: используйте SynchronousQueue из стандартной библиотеки. Вы всё равно не сделаете лучше. Все четыре предложенные реализации неустойчивы против повторного вызова producer. В этом плане смешно видеть умные слова в ответе "что позволяет потоку писать данные достаточно быстро". Как он может писать достаточно быстро, если дизайн класса не предполагает перекачки более одного значения? Такой код в серьёзном продакшне недопустим. Не надо изобретать велосипеды.


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

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

И к этому вопросу много вопросов. Типа Int в стандартной библиотеке Java вообще нет, но допустим это особенность формы опроса и имелся в виду примитивный int. Почему можно его использовать? Человек, у которого больше двух миллиардов рублей на счету, будет очень недоволен. Деление двух интов всегда округляется вниз, хотя вы пишете, что округлений нет. Наконец, любое число, представимое в int, представимо и в double с той же самой точностью. То есть любую операцию, которую вы можете сделать на int, вы можете сделать на double с не меньшей точностью. Причём у вас будет более точный результат деления и меньше рисков переполнения. Почему int считается правильным ответом, а double нет — совершенно неясно.


Нет, я понимаю стандартную мантру "используйте BigDecimal", но блин, вопрос-то надо правильно формулировать.

Должен ли класс, который планируется использовать в качестве ключа HashMap, быть полностью immutable?

Тут очень много вопросов. Начиная с того что понимать под immutable класс. Можете дать определение? Я знаю, что лучшие умы OpenJDK обсуждали этот термин долго и горячо, когда ввели вот эти все List.of и собирались их описать в документации. В итоге вообще отказались от слова immutable. Вот к примеру java.lang.String immutable или нет?


Также в "правильном" ответе ничего не написано про контракт Comparable. А если ключ реализует Comparable, но после изменения объекта результат сравнения получается другой? HashMap может сломаться.


Я бы ответил, что для любого объекта, используемого в качестве ключа (в том числе необязательно помещённого в Map, но и переданного в containsKey и т. д.), результат hashCode должен сохраняться на протяжении использования, а также для любой пары объектов, используемых в качестве ключа, результат equals и compareTo (при наличии) должен тоже сохраняться на протяжении использования. А что означает слово immutable — наплевать.

К сожалению, разработчики написали плохую хеш-функцию, и наблюдается значительная коллизия ключей. Метод equals() переопределен корректно. Какую алгоритмическую сложность поиска значения по ключу стоит ожидать?

Вы, конечно, ожидаете, что с Java 8 будет O(log n). Но это возможно только в том случае, если разработчики сделали свои объекты Comparable и корректно реализовали compareTo. Что было бы наивно ожидать от разработчиков, которые реализовали плохую хэш-функцию. Ни разу в жизни не видел объекта с плохой (но корректной) хэш-функцией и правильным compareTo одновременно. Вы видели?

Vavr невозможно использовать в реальных проектах. Вам нужен интероп с кучей других библиотек, которые про Vavr ни сном ни духом. А у вас и там, и сям простые имена классов называются одинаково со стандартными. В итоге ваш код превратится просто в ад. Хорошо и красиво для маленьких учебных проектов. Для кровавого продакшна — извините.

Изложение слабовато, конечно. "Присвоение ссылки объекту" — что это вообще за жесть? Как объекту можно присвоить ссылку?

Вы совершенно неправы. Все фичи продуманные. Над некоторыми думали годами и продолжают думать. И то что завезли — switch, instanceof, record — это маленькие куски более общей картины, которая соберётся позднее. Критика на уровне "фу, бяка" без конструктива не делает чести никому.

Вы жалуетесь что чего-то нету, когда оно на самом деле есть? Оригинально.


И если вам кажется, что фичи несвязанные и висящие в воздухе, попробуйте подумать с другой стороны. А может вам это только кажется? Может, вы чего-то не знаете? Может, всё-таки это делали люди не глупее вас?

Закройте кавычку левее. Положением закрывающей кавычки можно регулировать положение отступа.

Деструктуризация рекордов планируется в Java 15 в виде превью-фичи. Уже JEP завели.


Не понял пассаж про лень и не осилили. К чему это? Кому лень? Кто не осилил?

Ещё такой момент. Компоненты рекорда — абсолютно важная часть его интерфейса, важнее всего остального. Поэтому они сверху, чтобы глядя на определение рекорда было ясно, что к чему. Поля же можно объявлять в любом месте класса, хоть после методов. Но они и не так важны.

Потому что это не поля, а компоненты рекорда. Поля генерируются по ним. Ещё по ним генерируются, например, параметры конструктора и геттеры. У компонентов могут быть особые аннотации, доступные через reflection. В общем, это новая конструкция языка. Странно делать её синтаксически такой же как другая конструкция. А разве большая разница как скобки ставить?

Не очень понял сути вопроса, если честно. Приведите пример ожидаемого поведения и реального.

Возможно, из-за неблагоприятной эпидемиологической обстановки. Но точно не знаю.

Мы, кстати, обсуждаем реализацию из AbstractSet, а не возможную специализацию в HashSet. Конечно, когда мы больше знаем хотя бы про свой Set, нам будет проще выделить fast-path.

Возможно, метода retainAll вообще не должно было быть.

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


Зато сейчас у removeAll вообще не определена семантика

Это правда. Я лишь хотел показать, что вопрос "как правильно сделать" гораздо менее тривиальный, чем кажется, и мгновенное "разумеется" вовсе не так разумеется. Любое решение будет набором компромиссов.


Я исхожу из того, что стандартная библиотека должна работать предсказуемо.

Вариант всегда использовать contains целевой коллекции настолько же предсказуем. Ты вот делаешь неявное предположение, что у переданной коллекции iterator.next() быстрый, а это может быть и не так. К примеру, коллекция может быть фильтруемой на лету вьюшкой над большим сетом. Степень предсказуемости абсолютно одинаковая, она в любом случае зависит от устройства переданной коллекции, и с этим ничего не сделаешь.


Библиотека Guava могла бы и предоставить свою реализацию removeAll, принимающую MultiSet, в статическом хелпере.

Во-первых, это не нужно, потому что достаточно сделать mySet.removeAll(multiSet.toElementSet()) (подразумевая твою реализацию). Во-вторых, речь о неожиданных перформансных эффектах. Как ты обучишь каждого пользователя не использовать стандартный метод (или использовать его нестандартно) там, где он работает, выдаёт правильный результат и выполняется быстро на небольших тестовых данных? Либо ждать пока обожжётся (что мы, кстати, имеем в обсуждаемом примере), либо ожидать, что каждый пользователь прочитает и запомнит всю документацию от корки до корки (глупо), либо прокачивать статический анализ (вариант хороший, но ненадёжно).

Ладно, но есть метод retainAll, который реализован через обход нашей коллекции. Причём его реализовать через обход переданной коллекции невозможно без использования O(N) дополнительной памяти. Выходит, у removeAll по твоему предложению будет contains-семантика текущей коллекции, а у retainAll будет contains-семантика переданной коллекции. Она может отличаться. Например, нам передан TreeSet с компаратором.


Далее, кто сказал, что известная асимптотика лучше? Например, моя задача требует передавать параметром Guava Multiset. Я знаю, что contains в нём очень быстрый. Мне может интуитивно кажется, что обойти его тоже быстро, даже если там элементы с огромным количеством повторов. По факту же обход будет включать в себя все повторы, и я также получу провал в производительности на ровном месте.

А какую ветку из исходного кода оставить, если убрать проверку?

Information

Rating
Does not participate
Location
Новосибирск, Новосибирская обл., Россия
Registered
Activity