Comments 30
Красивая схема классов. Я так понимаю, это IntellijIDEA генерирует такую?
В английском нет такого слова «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-ти элментов :(.
Возможно не так библиотека.
Но как альтернативу конечно тоже можно использовать.
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>20040616</version>
</dependency>
И не увидел как можно сделать MultiKey длиней 5-ти элментов :(.
Возможно не так библиотека.
Но как альтернативу конечно тоже можно использовать.
Cortege
не самое главно что мне хотелось показать. Если рассматривать Cortege
как банальный контейнер для цепочки объектов, то проще использовать простой массив. :)Более интересным с моей точки зрения является не кортеж, а коллекции CortegeSet и CortegeList.
Возможность использовать их как альтерантиву физической таблицы подобно как в реляционных базах, но в памяти.
Основной областью применения таких конструкций я вижу в первую очередь в случаях, когда нужно манипулировать с данными в таблице (искать, изменять, добавлять, удалять строки и/или элементы), но когда по окончанию жизненного цикла сама таблица больше не нужна (не сохраняется в базу данных). Например при формировании отчета.
Писал когда-то похожую библиотеку, теперь жду от оракла включения 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)
, и далее внутри вашего кортежа храните всю эту же информацию о типах, потом можно дёргать и по индексу и прочее, что вы описали ниже. Нет?Я именно о таком решении уже думал, но пока не решился на включение его в релиз:
Действительно, осуществлять проверку в runtime можно будет достаточно легко.
Но есть два минуса:
1. декларация кортежа более трех элементов (основная область применения) будет очень длинной :(
2. к сожалению проверка будет только на runtime мне кажется этого мало, хочется придумать красивое и компактное решение для котроля на этапе компиляции.
Но я полностью с Вами согласен, что предложеное решение позволит повысить контроль над типами. Очень возможно что в следующий релиз войдет Ваше решение. Спасибо.
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 у вас возвращает бесконтрольный на этапе компиляции объект.
Да, Вы правы:
С контролем типов есть большие трудности. Мне очевидно следует полностью пересмотреть идею хранения и контроля типов в кортеже. Это была первая, но возможна не самая удачная попытка. Именно для того чтобы как можно полней осознать все за и против этого способа храннеия кортежа я и вынес на обсуждение эту тему. Но с моей точки зрения всеже есть и явные «фишки» у такого рекурсивной способа описания структуры. Возможно кому-то будет удобно его применить совершенно в другой области. :)
Всеже справедливости ради надо сказать, что все так сконцентрировались на кортеже, но практически никто не смотрел на коллекции. В них собственно и весь «сахар» (я же писал о методах findAny и extract). В следующей версии скорее всего будет другая сруктура у кортежа, но то, что получилось сделать в коллекциях я постараюсь сохранить.
Я имею в виду именно сам метод create у вас возвращает бесконтрольный на этапе компиляции объект.
С контролем типов есть большие трудности. Мне очевидно следует полностью пересмотреть идею хранения и контроля типов в кортеже. Это была первая, но возможна не самая удачная попытка. Именно для того чтобы как можно полней осознать все за и против этого способа храннеия кортежа я и вынес на обсуждение эту тему. Но с моей точки зрения всеже есть и явные «фишки» у такого рекурсивной способа описания структуры. Возможно кому-то будет удобно его применить совершенно в другой области. :)
Всеже справедливости ради надо сказать, что все так сконцентрировались на кортеже, но практически никто не смотрел на коллекции. В них собственно и весь «сахар» (я же писал о методах findAny и extract). В следующей версии скорее всего будет другая сруктура у кортежа, но то, что получилось сделать в коллекциях я постараюсь сохранить.
Хм. А вот авторы Guava: Google Core Libraries против кортежей. Пишут, что:
code.google.com/p/guava-libraries/wiki/IdeaGraveyard#Tuples_for_n_%3E=_2
И правда, пара пар трех кортежей двух пар звучит зловеще:)
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);
Мне честно очень жаль, что Ваша грусть столь велика.
Но мне кажется Вы привели не совсем честный пример, отношение к которому не имеет моя библиотека. Я какраз хотел уйти от подобный кашмарных выражений типа
Конечно отчасти Ваше замечание на счет громоздкости декларации кортежа справедливо, на данный момент я еще не придумал более компактной формы декларации типов, без потери неограниченности длины кортежа.
Но мне кажется Вы привели не совсем честный пример, отношение к которому не имеет моя библиотека. Я какраз хотел уйти от подобный кашмарных выражений типа
Pair<List<Quadruple<String, String, String, String>>
Но конечно же я не могу с Вами не согласиться в том, что название интрефейса Cortege
возможно не очень удачно. Обязуюсь отнестись к Вашему замечанию серъезно и постараться решить этот вопрос.Конечно отчасти Ваше замечание на счет громоздкости декларации кортежа справедливо, на данный момент я еще не придумал более компактной формы декларации типов, без потери неограниченности длины кортежа.
pastebin.com/xzJamfC0
Посмотрите как мы доставали дженерики в рантайме. Надеюсь поможет: )
За статью пятерочка
Посмотрите как мы доставали дженерики в рантайме. Надеюсь поможет: )
За статью пятерочка
О боги, какой кошмар. Вот именно из-за таких примеров над нами, яверами, и издеваются за наши громоздкие конструкции поверх всего.
Смысл кортежа для программиста — это удобный способ передать или хранить пачку значений. Синтаксический сахар, ведь всегда же можно под конкретный набор передаваемых типов создать класс вроде РезультатМетодаА. И вот ваш синтаксический сахар, он еще и совсем не сладкий, он мало того что горький (нечитаемый), так еще и глубоко теоретический. Вот зачем, зачем вам понадобилось вот это условие:
Кому от этого станет лучше? Часто вы в своей практике передавали кортежи длиной в 10 элементов? Если и да, то это место, которому точно помог бы рефакторинг.
Короче, я вот к чему. Код с использованием такой конструкции неудобен (.nextElement().nextElement()? правда? и это при заявленной неограниченной длине? что за лапша с ним станет при длине кортежа, скажем, в 20?) и, что хуже, не читаем. Решения, просто дающие ограниченный набор шаблонных классов ограниченной длины (будь то Pair, Triplet, etc., или Tuple2, Tuple3, Tuple10 и т.д.) куда как удобнее в использовании, не удовлетворяя при этом единственному, глубоко теоретическому условию.
А главное, все так аккуратно и точно сделано, залюбуешься. Эту бы энергию да на мирные цели…
Смысл кортежа для программиста — это удобный способ передать или хранить пачку значений. Синтаксический сахар, ведь всегда же можно под конкретный набор передаваемых типов создать класс вроде РезультатМетодаА. И вот ваш синтаксический сахар, он еще и совсем не сладкий, он мало того что горький (нечитаемый), так еще и глубоко теоретический. Вот зачем, зачем вам понадобилось вот это условие:
Кортеж должен быть неограниченным по длине и типу
Кому от этого станет лучше? Часто вы в своей практике передавали кортежи длиной в 10 элементов? Если и да, то это место, которому точно помог бы рефакторинг.
Короче, я вот к чему. Код с использованием такой конструкции неудобен (.nextElement().nextElement()? правда? и это при заявленной неограниченной длине? что за лапша с ним станет при длине кортежа, скажем, в 20?) и, что хуже, не читаем. Решения, просто дающие ограниченный набор шаблонных классов ограниченной длины (будь то Pair, Triplet, etc., или Tuple2, Tuple3, Tuple10 и т.д.) куда как удобнее в использовании, не удовлетворяя при этом единственному, глубоко теоретическому условию.
А главное, все так аккуратно и точно сделано, залюбуешься. Эту бы энергию да на мирные цели…
Sign up to leave a comment.
Кортежи объектов в Java и их коллекции