Поотнимаю немного хлеб у Лягуха и напишу пост про джаву.
Я люблю джаву. За её строгость, за типизацию, за ООП, за огромное количество готовых разработок и за богатую стандартную библиотеку.
В частности джава славится своими коллекциями и интерфейсами (читай контрактами).
Коллекции тут на любой вкус. Есть списки (листы), карты (мапы), множества (сеты), очереди (деки) и стеки. Каждый тип коллекции имеет несколько реализаций. Например, лист может быть реализован на базе нерасширяемого массива, или, например, на основе связного списка. Часть реализаций потокобезопасные, а часть могут подкинуть приколы в мнргопоточке :)
С интерфейсами такая же ситуация, их ооочень много. Часть интерфейсов обрабатывается самой JVM. Например, Serializable разрешает виртуальной машине применять к классу штатный механизм бинарной сериализации. А Iterable разрешает перебирать объект в цикле for each (для каждого) - круто же! Реализовали один метод и теперь объект можно циклом обходить.
Часть интерфейсов - прикладные.
Например, задача интерфейса Comparable - дать единый метод сравнения объектов одного класса. Сказать, что этот объект "больше", "меньше" или "равен" другому объекту именно в плане порядка/сортировки. Да даже List - это тоже интерфейс. Если писать код "правильно", опираясь на интерфейсы, то реализацию конкретного листа при необходимости можно менять безболезненно.
Какая может быть необходимость?
В грядущем (и долгожданном) релизе BSL Language Server под версией 0.20.0 появится важная фича - добавленный пару релизов назад механизм Reference Index, хранящий данные о вызове всех методов в коде и помогающий делать всякие "переход к определению", "поиск мест использования" и прочие всплывающие подсказки, научился хранить ещё и данные обо всех используемых переменных - где они были объявлены/им были присвоены значения и где к этим переменным было обращение. По всей кодовой базе.
Конечно же, это довольно сильно ударило по объёму занимаемой оперативной памяти. Если в релизе 0.19 данные индекса ПО вызовам методов в УХ занимали чуть меньше 100 мегабайт оперативной памяти, то загрузка в индекс всех данных об используемых переменных резко подняла этот показатель до почти 800 (!) мегабайт. Так как вопрос производительности работы с индексом не стоял (спасибо Эдуарду за несколько подходов к оптимизации), надо было попробовать снизить затраты памяти, пускай и жертвуя толикой производительности.
В качестве основного хранилища данных ссылок в индексе использовался ConcurrentHashMap - это почти как обычный HashMap, хранящий данные в хэш-таблице на основе, собственно, хэш-кода от ключа
Для переезда на эту мапу пришлось немного подправить код. В отличие от первоначального варианта эта мапа - отсортированная по ключам, а значит объекты нужно тоже сделать сортируемыми, то есть реализовать в них интерфейс Comparable.
Над реализацией метода сравнения я думал примерно ХеракХеракИГотово - если объекты равны между собой, значит они равны и по порядку. А если не равны, возьмём их хэш-код (для этого у каждого объекта в джаве есть соответствующий метод) и сравним их между собой. У кого хэш-код больше, тот и "больше" с точки зрения сортировки. А если меньше, то соответственно "меньше". Простота и красота, казалось бы... Побенчмаркали, потестили и влили.
А потом началось странное...