Конечно, это возможно, и даже проще с Гуавой :) Используйте 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();
}
}
возможная реализация stringLengthFunction
, использованная в примере с Guava.
Наконец, в Java 8 весь фрагмент кода может быть еще проще, поскольку ссылки на lambas и методы достаточно кратки, чтобы их можно было вставить в строку:
ImmutableListMultimap<E, E> indexed = Multimaps.index(list, String::length);
Для примера с чистой Java 8 (без гуавы), используя Collector.groupingBy
см. Ответ Джеффри Босбума , хотя в этом подходе есть несколько отличий:
- не возвращает
ImmutableListMultimap
, а Map
со значениями Collection
,
Нет никаких гарантий относительно типа, изменчивости, сериализуемости или поточной безопасности возвращаемой карты ( 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);
}
});
// or the same view, but with Java 8 lambdas:
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 : Как Петр Гладких упоминает в комментарии ниже , если Collection<List<E>>
достаточно, приведенный выше пример может быть проще:
Collection<List<E>> grouped = indexed.asMap().values();