当然可以,而且使用Guava更容易 :) 使用Multimaps.index(Iterable, Function)
:
ImmutableListMultimap<E, E> indexed = Multimaps.index(list, groupFunction)
如果您提供具体的使用案例,那么展示它的操作就更容易了。
来自文档的示例:
List<String> badGuys =
Arrays.asList("Inky", "Blinky", "Pinky", "Pinky", "Clyde");
Function<String, Integer> stringLengthFunction = ...;
Multimap<Integer, String> index =
Multimaps.index(badGuys, stringLengthFunction);
System.out.println(index);
打印
{4=[Inky], 6=[Blinky], 5=[Pinky, Pinky, Clyde]}
如果在您的情况下GroupFunction被定义为:
GroupFunction<String> groupFunction = new GroupFunction<String>() {
@Override public String sameGroup(final String s1, final String s2) {
return s1.length().equals(s2.length());
}
}
然后它会被翻译为:
Function<String, Integer> stringLengthFunction = new Function<String, Integer>() {
@Override public Integer apply(final String s) {
return s.length();
}
}
这是可能在Guava示例中使用的stringLengthFunction
实现。
最后,在Java 8中,整个代码片段甚至可以更简单,因为lambda表达式和方法引用足够简洁,可以内联:
ImmutableListMultimap<E, E> indexed = Multimaps.index(list, String::length);
针对纯Java 8(不使用Guava)的例子,使用Collector.groupingBy
请参见Jeffrey Bosboom的答案,尽管这种方法存在一些差异:
- 它不返回
ImmutableListMultimap
,而是带有Collection
值的Map
,
返回的Map类型、可变性、可序列化性或线程安全性没有任何保证(source),
- 相比于Guava+方法引用,它略微冗长。
编辑: 如果您不关心索引键,您可以获取分组的值:
List<List<E>> grouped = Lists.transform(indexed.keySet().asList(), new Function<E, List<E>>() {
@Override public List<E> apply(E key) {
return indexed.get(key);
}
});
List<List<E>> grouped = Lists.transform(indexed.keySet().asList(), indexed::get);
这个功能可以让你获得一个 Lists<List<E>>
视图,其内容可以轻松地复制到 ArrayList
中,或者像你最初想要的那样直接使用。另外请注意,indexed.get(key)
是不可变的 ImmutableList
。
// bonus: similar as above, but not a view, instead collecting to list using streams:
List<List<E>> grouped = indexed.keySet().stream()
.map(indexed::get)
.collect(Collectors.toList());
编辑2: 正如Petr Gladkikh在下面的评论中提到的, 如果Collection<List<E>>
足够,上面的示例可能会更简单:
Collection<List<E>> grouped = indexed.asMap().values();
indexed.asMap().values()
可能已经足够得到Collection<List<E>>
。 - Petr Gladkikh