使Multimap仅在Java中按键排序

Oli*_*ire 24 java sorting multimap guava

我想有一个c.g.c.c.Multimap仅基于键排序的.不应对值进行排序.我试图用番石榴来构建一些东西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;
  }
}
Run Code Online (Sandbox Code Playgroud)

我已经考虑过获取一些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());
}
Run Code Online (Sandbox Code Playgroud)

打印:

1 -> c // or switched with line below
1 -> e
2 -> a
3 -> b // or switched with line below
3 -> d
Run Code Online (Sandbox Code Playgroud)

Col*_*inD 22

Multimaps.index返回一个ImmutableListMultimap,因此在创建它之后您将无法对其进行排序.但是,您可以首先创建一个您Iterable<MyObject>和Feed 的排序副本,以便Multimap.index... ImmutableListMultimap保持事物的顺序与给定的顺序相同.

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

另一种选择可能是创建一个TreeMultimapOrdering.arbitrary()用作Comparator值.

  • 您还可以使用ImmutableMultimap.builder().orderKeysBy(); 或者您可以使用Multimaps.newMultimap(),它允许您选择支持映射和集合(使用TreeMap,比如,ArrayList). (14认同)
  • 很好......之前没有注意到`ImmutableMultimap.builder().orderKeysBy()`. (3认同)

gde*_*ohn 16

MultimapBuilder 在Guava 16中引入:

<K extends Comparable<? super K>, V> ListMultimap<K, V> multimap() {
    return MultimapBuilder.treeKeys().linkedListValues().build();
}
Run Code Online (Sandbox Code Playgroud)

这使您的密钥按其自然顺序排序(treeKeys()也过载以接受自定义比较器),并且与每个密钥关联的值保持在LinkedList(ArrayList并且HashSet是其他选项之中).


Tre*_*son 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);
            }
        });
}
Run Code Online (Sandbox Code Playgroud)