1. ホーム

[解決済み】Java SE 8はPairsとTuplesのどちらを採用していますか?

2022-04-12 12:07:06

質問

Java SE 8 の遅延関数操作で遊んでいるのですが、次のようにしたいのです。 map インデックス i をペア/タプルに (i, value[i]) であれば filter に基づいて、2番目の value[i] 要素で出力し、最後にインデックスだけを出力する。

これでも私は苦しまなければならないのか。 C++のPair&l,R>に相当するものは、Javaでは何ですか? ラムダとストリームの大胆な新時代に?

更新しました。 私はかなり単純化した例を示しましたが、この例には@dkatzelが以下の回答の1つで提示したきちんとした解決策があります。しかし、それは ではなく を一般化することができます。そこで、より一般的な例を追加してみます。

package com.example.test;

import java.util.ArrayList;
import java.util.stream.IntStream;

public class Main {

  public static void main(String[] args) {
    boolean [][] directed_acyclic_graph = new boolean[][]{
        {false,  true, false,  true, false,  true},
        {false, false, false,  true, false,  true},
        {false, false, false,  true, false,  true},
        {false, false, false, false, false,  true},
        {false, false, false, false, false,  true},
        {false, false, false, false, false, false}
    };

    System.out.println(
        IntStream.range(0, directed_acyclic_graph.length)
        .parallel()
        .mapToLong(i -> IntStream.range(0, directed_acyclic_graph[i].length)
            .filter(j -> directed_acyclic_graph[j][i])
            .count()
        )
        .filter(n -> n == 0)
        .collect(() -> new ArrayList<Long>(), (c, e) -> c.add(e), (c1, c2) -> c1.addAll(c2))
    );
  }

}

これは 不正確 の出力は [0, 0, 0] に対応する カウント である3つのカラムに対して、すべて false . 私が必要とするのは インデックス この3つの列の 正しい出力は次のようになります。 [0, 2, 4] . どうすればこの結果を得ることができますか?

どのように解決するのですか?

UPDATEしてください。 この回答は、元の質問に対するものです。 Java SE 8 には Pairs と Tuples がありますか? (OPはより完全な例で質問を更新しましたが、どのようなPair構造も使用せずに解決できるようです。[OPからの注意:以下は もう一つの正解 .]


簡単に言うと、「ノー」です。自分で作るか、それを実装しているいくつかのライブラリのうちの1つを持ち込む必要があります。

を持つことは Pair クラスは、少なくとも一度は提案され、却下されたことがあります。参照 この議論スレッド OpenJDKのメーリングリストの1つである。トレードオフは明白ではありません。一方では、他のライブラリやアプリケーションコードに多くのPair実装が存在します。これは必要性を示しており、このようなクラスをJava SEに追加することで、再利用と共有を促進することができます。一方、Pairクラスがあると、必要な型や抽象化を作らずにPairやコレクションから複雑なデータ構造を作るという誘惑が増えます。(これは、以下の言い換えです。 ケビン・ブーリオンのメッセージ そのスレッドから)

そのメールスレッドを全部読むことをみんなにお勧めします。驚くほど洞察力に富んでいて、誹謗中傷もない。かなり説得力がある。このスレッドが始まったとき、私は「ああ、Java SEにはPairクラスがあるべきだ」と思ったのですが、スレッドが終わりに近づくころには、私の考えは変わっていました。

ただし、JavaFXでは javafx.util.Pair クラスがあります。JavaFXのAPIは、Java SEのAPIとは別に発展してきた。

リンク先の質問からわかるように JavaでC++のPairに相当するものは何ですか? このように一見シンプルなAPIを取り巻くデザインスペースは非常に大きいのです。オブジェクトは不変であるべきなのか?シリアライザブルであるべきなのか?比較可能であるべきなのか?クラスはfinalであるべきかどうか?2つの要素は順番に並べるべきか?インターフェースかクラスか?なぜペアで止めるのか?なぜトリプル、クワッド、Nタプルではないのか?

そしてもちろん、要素の命名には必然的に二者択一が迫られます。

  • (a, b)
  • (一番目、二番目)
  • (左、右)
  • (car、cdr)
  • (foo, bar)
  • などです。

これまでほとんど言及されてこなかった大きな問題として、Pairsとプリミティブの関係があります。もし (int x, int y) 2次元空間の点を表すデータムは、これを Pair<Integer, Integer> を消費します。 3つのオブジェクト の代わりに、2つの32ビットワードを使用します。さらに、これらのオブジェクトはヒープ上に存在しなければならず、GCオーバーヘッドが発生します。

Streamsと同様に、Pairsにもプリミティブな特殊化が必要であることは明らかでしょう。見たいものです。

Pair
ObjIntPair
ObjLongPair
ObjDoublePair
IntObjPair
IntIntPair
IntLongPair
IntDoublePair
LongObjPair
LongIntPair
LongLongPair
LongDoublePair
DoubleObjPair
DoubleIntPair
DoubleLongPair
DoubleDoublePair

でも IntIntPair の場合、ヒープ上に1つのオブジェクトを必要とします。

これらは、もちろん、関数型インターフェースの普及を彷彿とさせるものです。 java.util.function もし、APIを肥大化させたくないのであれば、どれを省けばいいのだろうか。また、これだけでは不十分で、たとえば以下のような特殊化も必要だと主張することもできます。 Boolean も追加すべきです。

私の感覚では、もしJavaが大昔にPairクラスを追加していたとしても、それは単純な、あるいは単純化されたもので、今想像している多くのユースケースを満たすことはできなかったと思います。もしPairがJDK1.0の時代に追加されていたら、おそらくmutableになっていただろうと考えてみてください! (java.util.Dateを見てください)人々はそれで満足したでしょうか?私の推測では、もしJavaにPairクラスがあったとしても、それはちょっと、あまり役に立たないもので、誰もが自分のニーズを満たすために独自のものを開発し、外部ライブラリにさまざまなPairやTupleの実装があり、人々はJavaのPairクラスをどう修正するかについてまだ議論/考察を続けていることでしょう。言い換えれば、現在と同じような状況です。

一方、根本的な問題である、JVM(最終的にはJava言語)での 値型 . こちらをご覧ください 値の状態 のドキュメントを参照してください。これは予備的、推測的な作業であり、JVMの観点からの問題のみをカバーしていますが、すでにその背後にあるかなりの量の考えをもっています。もちろん、これがJava 9に入るという保証はありませんし、どこにも入らないという保証もありませんが、このトピックに関する現在の考え方の方向性を示しています。