Pull to refresh

Comments 30

Красивая схема классов. Я так понимаю, это IntellijIDEA генерирует такую?
Жаль Community Edition так не умеет, только Ultimate
В английском нет такого слова «cortege» в математическом смысле. Есть «tuple».
В простых случаях хватает org.apache.commons.collections.keyvalue.MultiKey из commons-collections
Возможно и хватит. А если нужно больше 5-ти элементов? и MultiKey не имеет контроля типов элементов.
Если брать не абстрактные примеры, то для такого случая уже стоило бы сделать класс для значения. (В общем-то, его иногда стоит сделать даже для 2-х элементов)
В MultiKey можно хоть сколько объектов хранить. Контроля типов нет. Ну я и говорю в простых случаях.
Я загрузил
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>20040616</version>
</dependency>

И не увидел как можно сделать MultiKey длиней 5-ти элментов :(.
Возможно не так библиотека.
Но как альтернативу конечно тоже можно использовать.
Нужно использовать конструктор MultiKey(Object[] keys), в котором можно указать массив ключей.
Cortege не самое главно что мне хотелось показать. Если рассматривать Cortege как банальный контейнер для цепочки объектов, то проще использовать простой массив. :)
Более интересным с моей точки зрения является не кортеж, а коллекции CortegeSet и CortegeList.
Возможность использовать их как альтерантиву физической таблицы подобно как в реляционных базах, но в памяти.

Основной областью применения таких конструкций я вижу в первую очередь в случаях, когда нужно манипулировать с данными в таблице (искать, изменять, добавлять, удалять строки и/или элементы), но когда по окончанию жизненного цикла сама таблица больше не нужна (не сохраняется в базу данных). Например при формировании отчета.
CortegeSet очень похож на LinkedHashSet, а CortegeLinkedList на LinkedList, плюс стоит задуматься о тормозах при обращении к LinkedList по индексу и о постоянном (без кеширования) вычислении hashCode в Cortege.
Писал когда-то похожую библиотеку, теперь жду от оракла включения project lambda в новую JDK.
// создание инстанса кортежа:
Cortege<Long, Cortege<String, Cortege.End>> cortegeLS = CortegeChain.create(2);

Следует обратить внимание на аргумент метода create. В связи с тем, что в Java дженерики существуют лишь на этапе компиляции, и добраться к ним в runtime я «законных» методов не нашел :(, пришлось «заплатить» за это такой ценой. Суть этого параметра — декларация глубины создаваемого кортежа. Но в виду того, что разработчик как правило знает кол-во элементов, необходимость указания этого параметра не должно вызывать больших проблем.

примечание: Но все же, если кто-то может предложить свое решение это проблемки с параметром — я буду чрезвычайно благодарен.
Понятно, что в рантайме такой информации вы и не получите напрямую. Но первое что приходит в голову (и подобным образом в таких случаях делается):
Cortege<Long, Cortege<String, Cortege.End>> cortegeLS = CortegeChain.create(Long.class,String.class);
, соответственно create какая-то такая:
create(Class... c)
, и далее внутри вашего кортежа храните всю эту же информацию о типах, потом можно дёргать и по индексу и прочее, что вы описали ниже. Нет?
Я именно о таком решении уже думал, но пока не решился на включение его в релиз:
Cortege<Long, Cortege<String, Cortege.End>> cortegeLS = CortegeChain.create(Long.class,String.class);

Действительно, осуществлять проверку в runtime можно будет достаточно легко.
Но есть два минуса:
1. декларация кортежа более трех элементов (основная область применения) будет очень длинной :(
2. к сожалению проверка будет только на runtime мне кажется этого мало, хочется придумать красивое и компактное решение для котроля на этапе компиляции.

Но я полностью с Вами согласен, что предложеное решение позволит повысить контроль над типами. Очень возможно что в следующий релиз войдет Ваше решение. Спасибо.
Для этапа компиляции по-любому надо дополнительно параметризовать генериками сам метод create. Это два несвязанных случая. Но ведь и сейчас он у вас совершенно без всякого контроля типов возвращает кортеж. Или я чего-то не понял?
Да, Вы правы, усилить контроль над типами элеменентов кортежа стоит. Ваше предложение на счет create(Class<? extends Object>... types) разумно. Но опять же остаются грустные случаи когда программист сможет продекларировать кортеж с одним набором типов и кол-вом элементов, но вызвать приэтом метод create с совершенно иным набором типов и их кол-вом. Приведу пример:
Cortege<Long, Cortege<String, Cortege.End>> cortegeLS = CortegeChain.create(Character.class, Integer.class, String.class);
Я к сожелению не могу придумать как проверить такую ситуацию на этапе компиляции. :( Если Вы можете подсказать решение, буду очень благодарен.
На счет:
Но ведь и сейчас он у вас совершенно без всякого контроля типов возвращает кортеж. Или я чего-то не понял?

Не везде контроль отсутствует. Если брать элементы поочередно методом getValue() тип контролируется на этапе компиляции.
Отсутствует контроль, когда происходит обращение к элементу по индексу как в getValue(int index).
Не везде контроль отсутствует. Если брать элементы поочередно методом getValue() тип контролируется на этапе компиляции.
Это то понятно, там у вас в некоторых местах так и пишется в комментариях «с контролем типа». Я имею в виду именно сам метод create у вас возвращает бесконтрольный на этапе компиляции объект.
Да, Вы правы:
Я имею в виду именно сам метод create у вас возвращает бесконтрольный на этапе компиляции объект.

С контролем типов есть большие трудности. Мне очевидно следует полностью пересмотреть идею хранения и контроля типов в кортеже. Это была первая, но возможна не самая удачная попытка. Именно для того чтобы как можно полней осознать все за и против этого способа храннеия кортежа я и вынес на обсуждение эту тему. Но с моей точки зрения всеже есть и явные «фишки» у такого рекурсивной способа описания структуры. Возможно кому-то будет удобно его применить совершенно в другой области. :)

Всеже справедливости ради надо сказать, что все так сконцентрировались на кортеже, но практически никто не смотрел на коллекции. В них собственно и весь «сахар» (я же писал о методах findAny и extract). В следующей версии скорее всего будет другая сруктура у кортежа, но то, что получилось сделать в коллекциях я постараюсь сохранить.
Хм. А вот авторы Guava: Google Core Libraries против кортежей. Пишут, что:
Tuple types are awful obfuscators. Tuples obfuscate what the fields actually mean (getFirst and getSecond are almost completely meaningless), and anything known about the field values. Tuples obfuscate method signatures: ListMultimap<Route, Pair<Double, Double>> is much less readable than ListMultimap<Route, LatLong>.


code.google.com/p/guava-libraries/wiki/IdeaGraveyard#Tuples_for_n_%3E=_2

И правда, пара пар трех кортежей двух пар звучит зловеще:)
Я более чем согласен. В большинстве своем — это тупо лень разрабочика создавать новый класс с читаемыми названиями (даже внутренний статический).
Согласен. Действительно есть трудность с пониманием смысла значения хронящегося в какой-либо позиции. Особенно когда тип элементов часто повторяется. Например,
Cortege<Long, Cortege<Long, Cortege<Long, Cortege.End>>> cortegeLLS = CortegeChain.create(); 

Конечно лучше когда есть контейнер с вразумительными геттерами.
Но в некоторых случаях может понадобиться получить фрагмент кортежа и рассматривать его как самостоятельную сущность. Cortege как в примере,
Cortege<Long, Cortege<Long, Cortege.End>> rightCortegeLS = cortegeLLS.nextElement();

Опять же, стоит обратить внимание на инструментарий, который дают имплементации коллекций как: CortegeSetи CortegeList. В посте есть пример использование некоторых возможностей. Например, найти подколлекцию по значению элемента в кортежах или по предикату. (методы findAny и extract)
Cortege<Long, Cortege<Long, Cortege<String, Cortege.End>>> any5 = cortegeSetLLS.findAny(1, 5L);
или
CortegeSet<Cortege<Long, Cortege<Long, Cortege<String, Cortege.End>>>> extractAll5 = cortegeSetLLS.extract(1, 5L);
UFO just landed and posted this here
Мне честно очень жаль, что Ваша грусть столь велика.
Но мне кажется Вы привели не совсем честный пример, отношение к которому не имеет моя библиотека. Я какраз хотел уйти от подобный кашмарных выражений типа
Pair<List<Quadruple<String, String, String, String>>
Но конечно же я не могу с Вами не согласиться в том, что название интрефейса Cortege возможно не очень удачно. Обязуюсь отнестись к Вашему замечанию серъезно и постараться решить этот вопрос.
Конечно отчасти Ваше замечание на счет громоздкости декларации кортежа справедливо, на данный момент я еще не придумал более компактной формы декларации типов, без потери неограниченности длины кортежа.
UFO just landed and posted this here
pastebin.com/xzJamfC0

Посмотрите как мы доставали дженерики в рантайме. Надеюсь поможет: )

За статью пятерочка
Спасибо большое! Очень интересная ссылка!
Подумаю как использовать.
UFO just landed and posted this here
О боги, какой кошмар. Вот именно из-за таких примеров над нами, яверами, и издеваются за наши громоздкие конструкции поверх всего.

Смысл кортежа для программиста — это удобный способ передать или хранить пачку значений. Синтаксический сахар, ведь всегда же можно под конкретный набор передаваемых типов создать класс вроде РезультатМетодаА. И вот ваш синтаксический сахар, он еще и совсем не сладкий, он мало того что горький (нечитаемый), так еще и глубоко теоретический. Вот зачем, зачем вам понадобилось вот это условие:

Кортеж должен быть неограниченным по длине и типу


Кому от этого станет лучше? Часто вы в своей практике передавали кортежи длиной в 10 элементов? Если и да, то это место, которому точно помог бы рефакторинг.

Короче, я вот к чему. Код с использованием такой конструкции неудобен (.nextElement().nextElement()? правда? и это при заявленной неограниченной длине? что за лапша с ним станет при длине кортежа, скажем, в 20?) и, что хуже, не читаем. Решения, просто дающие ограниченный набор шаблонных классов ограниченной длины (будь то Pair, Triplet, etc., или Tuple2, Tuple3, Tuple10 и т.д.) куда как удобнее в использовании, не удовлетворяя при этом единственному, глубоко теоретическому условию.

А главное, все так аккуратно и точно сделано, залюбуешься. Эту бы энергию да на мирные цели…
UFO just landed and posted this here
Sign up to leave a comment.

Articles