Javaのオブジェクトのタプルとそのコレクション

実際には、多くの場合、「ペア」( Pair<First, Second>



)、それほど頻繁ではない「トリナー」オブジェクト( Triplet<First, Second, Third>



)および関連オブジェクトの長いチェーンなどの構造を使用する必要があります。 これに関連して、私は常にJDK( java.lang.*



またはjava.util.*



)でなぜ標準的なPair<First, Second>



またはそれ以上の構造が存在しないのか疑問に思っていました。 多くのJavaプログラマーが独自の「ペア」実装を持っていると思います。 私も例外ではありません。



そして、多数の異なるタプルを使用する必要性に再び遭遇し、この問題に体系的に取り組むことにしました。 彼はプロジェクトの名前を思いつき、目標を設定し、時間のかかる実験の後、コードを投稿しました(git://github.com/telesik/rumba.git)。



私が達成したかったもの:



タプルの光の現象



そして、ここでCortege



インターフェースCortege





 public interface Cortege<V, T extends Cortege> { T setValue(V value); T nextElement(); <Vi> Vi getValue(int index) throws ClassCastException; // be careful with types. Type is not bounded int getDeep(); <Vi> void setValue(int index, Vi value); // be careful with types. Type is not bounded Cortege<V, T> setValues(Object... values); // be careful with types. Type is not bounded!!! V getValue(); static abstract class End<V, T extends Cortege<V, T>> implements Cortege<V, T> { } }
      
      





以下の図は、任意の長さと要素タイプのタプルを記述するためのメカニズムを明確に示しています

画像

図 1.任意の長さのタプルと要素のタイプを記述するメカニズム



しかし、実装がない場合の裸のインターフェースは何ですか? あります! 彼女の名前はCortegeChain



です。 名前にチェーンという単語が存在するのは、タプル内の要素のストレージを整理する方法によるものです。 将来的には、さまざまなタイプの使用に最適化された他の実装が存在することを期待しています。

CortegeChain



の実装では、メモリ使用量または速度に関して特定の最適化目標を設定しませんでした。 私が解決したかった主なタスクは、アイデアそのものを試すこと、弱点を見つけること、開発者に開かれた明白な機会と明白でない機会を特定することでした。



使用例



すぐに使用例を説明します。



 //   : Cortege<Long, Cortege<String, Cortege.End>> cortegeLS = CortegeChain.create(2);
      
      





createメソッドの引数に注意してください。 Javaジェネリックはコンパイル段階でのみ存在し、実行時にそれらに到達するための「正当な」メソッドを見つけられなかったという事実のために:(、私はそのような価格でそれを「支払う」必要がありました。このパラメーターの本質は作成されたタプルの深さの宣言です。開発者は通常要素の数を知っているので、このパラメーターを指定する必要は大きな問題にはなりません。



注:それでも、誰かがソリューションを提供できる場合、これはパラメーターの問題です。非常に感謝します。



ので、例

 //    // 1-  (    ,   ) cortegeLS.setValue(4L); cortegeLS.nextElement().setValue("str"); // 2-  (  ,   ) cortegeLS.setValue(4L).setValue("str"); // 3-  ( ,   ) cortegeLS.setValues(4L, "str");
      
      





今読んでいる

 // 1-  (    ,   ) Long valueA = cortegeLS.getValue(); // 2-  (    ,   ) String valueB = cortegeLS.nextElement().getValue(); // 3-  (    ,   ) Long valueC = cortegeLS.getValue(1); String valueD = cortegeLS.getValue(2);
      
      





タプルで他にできること:

1.タプルを「右側」に取得します。

 Cortege<String, Cortege.End> rightCortegeS = cortegeLS.nextElement(); //   Cortege.End rightCortegeEnd = cortegeLS.nextElement().nextElement();
      
      





2.「深さ」(タプルの要素数)を取得します

 int deep = cortegeLS.getDeep();
      
      





おそらくそれだけです。 しかし、すべてではありません! :)



タプルコレクション



理由でタプルを作成しました。 さて、このような構造を持っているので、友好的なコレクションファミリ( java.util.Collection



)に「結び付ける」のがいいでしょう。 すぐに言ってやった。 しかし、タプルをコレクションの要素として平凡に使用することは面白くありません。 java.util.Set



およびjava.util.List



インターフェイスの従来の実装を提供するコレクション全体の要素を検索、削除、変更するだけでなく、コレクションに格納されているタプルの個々の要素による検索、フィルタリング、列全体の変更なども行いたいです。これはリレーショナルテーブルにとっては自然なことです。



再び目標を設定します。



注:私が望んでいたすべての中で、最後の項目「ビュー」(リレーショナルデータベースのビューのアナログ)のみを実装することはできませんでした。 しかし、作業は進行中であり、おそらく近い将来、この有望なアイデアの実現が世界にもたらされるでしょう。



そして、ここで何が起こったのです:

 public interface CortegeCollection<T extends Cortege> extends Collection<T>, Iterable<T> { <T> boolean contains(int num, T obj); CortegeCollection<T> extract(int num, Object key); CortegeCollection<T> extract(Corteges.Predicate<T> predicate); // <C> CortegeCollection<T> view(int num, Corteges.Predicate<C> predicate); T findAny(int num, Object key); T findAny(Corteges.Predicate<T> predicate); <Vi> List<Vi> getColumnCopy(int num); <Vi> void fill(int num, Vi value); } public interface CortegeSet<T extends Cortege> extends CortegeCollection<T>, Set<T> { } public interface CortegeList<T extends Cortege> extends CortegeCollection<T>, List<T> { }
      
      







画像

図 2.タプルコレクションのトポロジ



タプルコレクションの使用例



Cortege



説明の場合のように、今ではおそらく価値がありますCortege



すぐに視覚的な使用例に進みます。

 public class ExampleCollections { public static void main(String[] args) { //   CortegeHashSet CortegeSet<Cortege<Long, Cortege<String, Cortege.End>>> cortegeHashSetLS = Corteges.newCortegeHashSet(2); for (long i = 0; i < 5; i++) { Cortege<Long, Cortege<String, Cortege.End>> cortegeLS = CortegeChain.create(2); cortegeLS.setValue(i).setValue("" + i); cortegeHashSetLS.add(cortegeLS); } for (Cortege cortege : cortegeHashSetLS) { System.out.println(cortege); } cortegeHashSetLS.add(CortegeChain.<Long, Cortege<String, Cortege.End>>create(2)); Cortege<Long, Cortege<String, Cortege.End>> cortegeIS = CortegeChain.create(2); System.out.println(cortegeHashSetLS.contains(cortegeIS)); cortegeIS.setValue(null).setValue("3"); System.out.println(cortegeIS); System.out.println(cortegeHashSetLS.contains(cortegeIS)); System.out.println(cortegeHashSetLS.contains(1, 3L)); Cortege<Long, Cortege<Long, Cortege<String, Cortege.End>>> cortegeLLS1 = CortegeChain.create(3); Cortege<Long, Cortege<Long, Cortege<String, Cortege.End>>> cortegeLLS2 = CortegeChain.create(3); Cortege<Long, Cortege<Long, Cortege<String, Cortege.End>>> cortegeLLS3 = CortegeChain.create(3); CortegeChain<String, CortegeChain<Long, CortegeChain<String, Cortege.End>>> cortegeSLS = CortegeChain.create(3); cortegeLLS1.setValue(1L); cortegeLLS1.nextElement().setValue(11L); cortegeLLS1.nextElement().nextElement().setValue("AAA"); cortegeLLS2.setValue(2L); cortegeLLS2.nextElement().nextElement().setValue("BBB"); cortegeLLS3.setValue(3L); cortegeLLS3.nextElement().setValue(33L); cortegeLLS3.nextElement().nextElement().setValue("AAA"); CortegeHashSet<Cortege<Long, Cortege<Long, Cortege<String, Cortege.End>>>> cortegeSetLLS = Corteges.newCortegeHashSet(cortegeLLS1.getDeep()); System.out.println(cortegeSetLLS.contains(cortegeLLS1)); cortegeSetLLS.add(cortegeLLS1); cortegeSetLLS.add(cortegeLLS2); cortegeSetLLS.add(cortegeLLS3); System.out.println(cortegeSetLLS.contains(cortegeLLS1)); for (Cortege<Long, Cortege<Long, Cortege<String, Cortege.End>>> cortege : cortegeSetLLS) { System.out.println(cortege); } System.out.println(cortegeSetLLS.contains(3, "AAA")); cortegeSetLLS.fill(1, 5L); cortegeSetLLS.fill(2, 8L); cortegeSetLLS.fill(3, "XXX"); for (Cortege<Long, Cortege<Long, Cortege<String, Cortege.End>>> cortege : cortegeSetLLS) { System.out.println(cortege); } // Collection<Cortege> corteges = cortegeSetLLS.extract(2, "111"); } }
      
      







まとめると



この例からわかるように、長いタプルのオブジェクトを格納および操作するための非常に便利なライブラリが得られました。 ライブラリの利点は次のとおりです。



ライブラリには、Cortege構造自体に加えて、よく知られているjava.util.Set



およびjava.util.List



を拡張する2種類のコレクションがありcom.rumba.cortege.CortegeList



com.rumba.cortege.CortegeSet



およびcom.rumba.cortege.CortegeList



)。



しかし、主にJavaのジェネリック宣言を「取得」できないことによって引き起こされる明らかな欠点があり、その結果、インデックスによってタプル要素にアクセスするときに型制御が失われます。 公平に、私は同様の問題を解決するライブラリを探し、 javatuplesのかなり興味深い実装を見つけました。 その中で、関連オブジェクトの「長い」チェーンを宣言する問題は、開発者の観点から「合理的な」タプルの単純な列挙によって解決されます。





おわりに



ライブラリでの作業中に、タプルとそのコレクションを操作するときに発生する最も典型的な、そして私の観点から、有用なタスクをカバーしようとしました。 残念ながら、すべての計画が実装されているわけではありませんが、完了した作業の一部が誰かに役立つことを願っています。 しかし、作業は継続され、無駄にならないことを願っています。

この記事とライブラリの建設的な適合を取得することは非常に興味深いでしょう。



便利なリンク



javatuples

実装する非常に興味深い試み




All Articles