27

リスト(またはセット)があるとします:

List<String> testList = Lists.newArrayList("assocX","srcT","destA","srcX", "don't care Y", "garbage", "srcB");

「src」で始まる用語が最初、「assoc」が 2 番目、「dest」が最後である自然な順序で用語をソート/グループ化する ImmutableList(Set) を取得したいと思います。用語にそれらが含まれていない場合は、結果のリストから削除する必要があります。

したがって、ここでの結果は「srcB」、「srcT」、「assocX」、「destA」です。

Iterables.filter または Predicates の組み合わせでこれを実行できると思いますが、表示されません。私が思うにそれを行う簡潔な方法があるに違いありません。

編集:リストの代わりにセットも機能します。

4

4 に答える 4

33

これら 3 つの接頭辞だけが重要である限り、次のようなものをお勧めします。

    Predicate<String> filter = new Predicate<String>() {
        @Override
        public boolean apply(String input) {
            return input.startsWith("src") || input.startsWith("assoc") || input.startsWith("dest");
        }
    };

    Function<String, Integer> assignWeights = new Function<String, Integer>() {
        @Override
        public Integer apply(String from) {
            if (from.startsWith("src")) {
                return 0;
            } else if (from.startsWith("assoc")) {
                return 1;
            } else if (from.startsWith("dest")) {
                return 2;
            } else {
                /* Shouldn't be possible but have to do something */
                throw new IllegalArgrumentException(from + " is not a valid argument");
            }
        }
    };

    ImmutableList<String> sortedFiltered = ImmutableList.copyOf(
            Ordering.natural().onResultOf(assignWeights).sortedCopy(
                    Iterables.filter(testList, filter)
            )
    );

フィルターと各プレフィックスの重みの両方を継続的に更新する必要があるため、フィルター処理または並べ替えを行うプレフィックスをさらに追加し始めると、このソリューションは間違いなくうまくスケールアウトしません。

于 2010-02-22T18:13:09.900 に答える
12

This Google Collections exampleをご覧ください。

Function<Fruit, String> getNameFunction = new Function<Fruit, String>() {
    public String apply(Fruit from) {
        return from.getName();
    }
};

Ordering<Fruit> nameOrdering = Ordering.natural().onResultOf(getNameFunction);

ImmutableSortedSet<Fruit> sortedFruits = ImmutableSortedSet.orderedBy(
    nameOrdering).addAll(fruits).build();

確かに、これは Set を返します。

于 2010-02-22T17:57:29.980 に答える
0

通常、このように明確に区別できるデータを照合するのは悪い設計です。あなたの場合、「assocX」と言うとき、「assoc」は「X」とは別の意味ですが、それらを一緒にマージします。

したがって、2 つのフィールドを持つクラスを設計することをお勧めします。次に、最初のフィールドで順序を作成し、2 番目のフィールドで別の順序を作成して、それらを結合できます (例: Ordering#compound())。これらのフィールドを文字列にマージする toString() メソッドを使用します。おまけとして、これにより共有によりメモリ使用量が大幅に削減される場合があります。

したがって、そのようなオブジェクトのリストをソートし、それらを印刷したい場合は、それらに対して toString() を呼び出すだけです。

于 2010-03-17T13:35:34.717 に答える
0

最初に述語を使用して不要な要素を削除し、Comparatorを実装してリストをソートする必要があると思います。

于 2010-02-22T17:55:09.860 に答える