25

c.g.c.c.Multimapキーのみに基づいてソートされたものが欲しいのですが。値はソートされるべきではありません。guavaを使用して何かを構築しようとしましTreeMultimapたが、値型が実装されていないため、使用できませんComparable

public class MyObject /* doesn't implement Comparable */ {
  private String name;
  private int score;
  // Getters/setters are implemented
  public static Function<MyObject,Integer> myObjectToScore {
    @Override public Integer apply (MyObject o) { return o.score; }
  }
  public static Multimap<Integer,MyObject> indexOnScore(Iterable<MyObject> i) {
    Multimap<Integer,MyObject> m = Multimaps.index(i, myObjectToScore());
    // Do the sort of the keys.
    return m;
  }
}

キーを取得し、並べ替えられたセット内のこれらの各キーを繰り返し処理してさまざまな値を取得することを考えましたが、この種のハックSortedSetを使用するのではなく、Guavaの既存の(まだ発見されていない)機能を使用することを望んでいました。

注:実際のオブジェクトでは意味がないため、MyObject実装は行いません。Comparable


入出力の例:

Set<MyObject> s = Sets.newHashSet(
  new MyObject("a", 2),
  new MyObject("b", 3),
  new MyObject("c", 1),
  new MyObject("d", 3),
  new MyObject("e", 1)
); // Assuming constructor MyObject(String name, int score)

for (Map.Entry<Integer, MyObject> e: MyObject.indexedOnScore(s).entries()) {
  System.out.printf("%d -> %s%n", e.getKey(), e.getValue().getName());
}

プリント:

1 -> c // or switched with line below
1 -> e
2 -> a
3 -> b // or switched with line below
3 -> d
4

8 に答える 8

22

Multimaps.indexを返すためImmutableListMultimap、作成後にソートすることはできません。ただし、最初にソートされたコピーを作成し、Iterable<MyObject>それをフィードして、与えられたのと同じ順序で物事を保持することもできますMultimap.indexImmutableListMultimap

public static ImmutableMultimap<Integer, MyObject> indexOnScore(Iterable<MyObject> i) {
  List<MyObject> sorted = Ordering.natural().onResultOf(myObjectToScore())
      .sortedCopy(i);
  return Multimaps.index(sorted, myObjectToScore());
}

別のオプションとして、 を作成して値の としてTreeMultimap使用することもできます。Ordering.arbitrary()Comparator

于 2011-03-31T15:07:32.260 に答える
8

OPの特定の状況は、不変のマルチマップ構築機能を使用して回答されたようですが、私は彼が求めていたものの可変バージョンが必要でした. それが誰かを助ける場合に備えて、私が最終的に作成した一般的な方法は次のとおりです。

static <K, V> Multimap<K, V> newTreeArrayListMultimap(
    final int expectedValuesPerKey)
{
    return Multimaps.newMultimap(new TreeMap<K, Collection<V>>(),
        new Supplier<Collection<V>>()
        {
            @Override
            public Collection<V> get()
            {
                return new ArrayList<V>(expectedValuesPerKey);
            }
        });
}
于 2011-11-03T23:33:59.330 に答える
1

Comparators を使用する場合は、TreeMultimapで実行できます。

キーの型と値の型 ( ?)のComparatorを作成します。MyObject次にcreate(Comparator keyComparator, Comparator valueComparator)を使用してマップを作成します。

Comparable を実装するよりも Comparator を使用する利点は、 Comparator をマップで必要な状況に固有のものにすることができ、一般にオブジェクトに影響を与えないことです。Comparator が equals と一致している限り、必要なことは何でもできます。

于 2011-03-31T14:42:35.227 に答える
1

これはどう:

    public static Multimap<Integer, MyObject> indexOnScore(Iterable<MyObject> i) {
        Multimap<Integer, MyObject> m = Multimaps.index(i, myObjectToScore());

        Multimap<Integer, MyObject> sortedKeys = Multimaps.newMultimap(
                Maps.<Integer, Collection<MyObject>>newTreeMap(),
                new Supplier<Collection<MyObject>>() {
                    @Override
                    public Collection<MyObject> get() {
                        return Lists.newArrayList(); // Or a Set if appropriate
                    }
                }
        );

        sortedKeys.putAll(m);

        return sortedKeys;
    }

Multimapただし、この場合、2 つの個別の を作成するオーバーヘッドが発生します。

于 2011-03-31T14:57:12.783 に答える