3

2つの機能が欲しいです。最初のは、コレクションが与えられると、述語を満たす要素を返します。述語は非常に高価になる可能性があり、結果が完全に消費されるわけではないため、最善の行動はビューを返すことであると考えました。したがって、一度実装すると、私のメソッドはGuavaのCollections2.filterをカプセル化するものにすぎません。

Collection<MyElement> getInterestingElements(Collection<MyElement> allElements) {
    return Collections2.filter(allElements, new Predicate<MyElement>() {
        @Override
        public boolean apply(MyElement element) {
            return element.isInteresting();  // call expensive function
        }
    });
}

(無実を保護するためにクラス名が変更されました)

2番目の関数は最初の関数を呼び出して次を返します。

  • コレクションにゼロまたは複数の要素が含まれている場合はnull。
  • コレクションに要素が1つしかない場合は、コレクションの唯一の要素。

つまり、この関数は、このコレクションがシングルトンである場合にのみ、コレクションのコンテンツを返します。

単純な実装は次のようになります。

MyElement getElementIfOnlyInterestingOne(Collection<MyElement> allElements) {
    Collection<MyElement> interestingElements = getInterestingElements(allElements);

    if (interestingElements.size() != 1){
        return null;
    }

    return Iterables.first(interestingElements, null);
}

しかし、willへの呼び出しsize()は(私が思うに)基礎となるコレクションのすべての要素の述語を評価します。最初の要素に興味がある場合、それは受け入れられません。

Iterables.getOnlyElement()を使用することもできますが、コレクションがシングルトンでない場合は例外がスローされます。これは頻繁に発生するはずであり、例外に依存してそれを行うのは悪い習慣だと思います。

したがって、手動で繰り返し、最初の要素を変数に格納し、2番目の要素がある場合はnullを返す必要があります。

私の質問は:これは問題ありませんが、私は車輪の再発明をしていませんか?グアバには非常に多くの魔法があるので、この問題はどこかで解決する必要がありisSingletonますgetSingleElementOrNull:)

4

3 に答える 3

10

「Guavaの方法」は、インスタンスを返すFluentIterableのメソッドを使用することです。あなたの場合:firstMatchOptional

MyElement interestingOrNull = FluentIterable.from(allElements)
    .firstMatch(new Predicate<MyElement>() {
      @Override
      public boolean apply(MyElement element) {
        return element.isInteresting();
      }
    })
    .orNull();

(さらに多くの「グアバウェイ」はnull結局使用されないでしょう...)

于 2013-02-22T11:26:43.507 に答える
7

1つの要素以外のものを含むフィルター処理されたコレクションが返される必要がある説明どおりにメソッドを実装する必要がある場合、null私が思いつくことができる最善の方法は、既に提案したソリューションです。

Collection<MyElement> interestingElements = getInterestingElements(allElements);
Iterator<MyElement> iterator = interestingElements.iterator();
if (!iterator.hasNext()) {
    return null;
}
MyElement first = iterator.next();
if (iterator.hasNext()) { // More than one element
    return null;
} else {
    return first;
}
于 2013-02-21T23:01:25.727 に答える
0

もちろん、上記のFluentIterableの提案では、問題のサイズ>2=>ヌル部分は処理されません。個人的には、Iterables.getOnlyValueアプローチを使用します。少し面倒ですが、コードが大幅に簡素化され、意図が明確になっています。

于 2013-02-28T00:50:19.923 に答える