Kkk*_*kev 14 java collections guava lambdaj
我有一个对象列表,我需要转换为一个映射,其中键是每个元素的函数,值是每个元素的另一个函数的列表.实际上,这是通过它们的功能对元素进行分组.
例如,假设一个简单的元素类:
class Element {
int f1() { ... }
String f2() { ... }
}
Run Code Online (Sandbox Code Playgroud)
以及这些的清单:
[
{ f1=100, f2="Alice" },
{ f1=200, f2="Bob" },
{ f1=100, f2="Charles" },
{ f1=300, f2="Dave" }
]
Run Code Online (Sandbox Code Playgroud)
那我想要一张地图如下:
{
{key=100, value=[ "Alice", "Charles" ]},
{key=200, value=[ "Bob" ]},
{key=300, value=[ "Dave" ]}
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以建议一种简洁的方式在Java中执行此操作而不进行迭代吗?LambdaJ的group方法与Guava的组合Maps.transform几乎可以实现,但group不生成地图.
Eti*_*veu 21
Guava有Maps.uniqueIndex(Iterable values,Function keyFunction)和Multimaps.index(Iterable values,Function keyFunction),但它们不会转换值.还有一些 请求添加你想要什么实用的方法,但现在,你必须使用Multimaps.index()和Multimaps.transformValues()将自己滚吧:
static class Person {
private final Integer age;
private final String name;
public Person(Integer age, String name) {
this.age = age;
this.name = name;
}
public Integer getAge() {
return age;
}
public String getName() {
return name;
}
}
private enum GetAgeFunction implements Function<Person, Integer> {
INSTANCE;
@Override
public Integer apply(Person person) {
return person.getAge();
}
}
private enum GetNameFunction implements Function<Person, String> {
INSTANCE;
@Override
public String apply(Person person) {
return person.getName();
}
}
public void example() {
List<Person> persons = ImmutableList.of(
new Person(100, "Alice"),
new Person(200, "Bob"),
new Person(100, "Charles"),
new Person(300, "Dave")
);
ListMultimap<Integer, String> ageToNames = getAgeToNamesMultimap(persons);
System.out.println(ageToNames);
// prints {100=[Alice, Charles], 200=[Bob], 300=[Dave]}
}
private ListMultimap<Integer, String> getAgeToNamesMultimap(List<Person> persons) {
ImmutableListMultimap<Integer, Person> ageToPersons = Multimaps.index(persons, GetAgeFunction.INSTANCE);
ListMultimap<Integer, String> ageToNames = Multimaps.transformValues(ageToPersons, GetNameFunction.INSTANCE);
// Multimaps.transformValues() returns a *lazily* transformed view of "ageToPersons"
// If we want to iterate multiple times over it, it's better to create a copy
return ImmutableListMultimap.copyOf(ageToNames);
}
Run Code Online (Sandbox Code Playgroud)
可重用的实用方法可以是:
public static <E, K, V> ImmutableListMultimap<K, V> keyToValuesMultimap(Iterable<E> elements, Function<E, K> keyFunction, Function<E, V> valueFunction) {
ImmutableListMultimap<K, E> keysToElements = Multimaps.index(elements, keyFunction);
ListMultimap<K, V> keysToValuesLazy = Multimaps.transformValues(keysToElements, valueFunction);
return ImmutableListMultimap.copyOf(keysToValuesLazy);
}
Run Code Online (Sandbox Code Playgroud)
我想我们可以通过使用Function<? extends E, K>或者其他东西来改进签名中的泛型,但我没有时间进一步钻研......
现在使用Java8,您可以这样做:
static class Element {
final int f1;
final String f2;
Element(int f1, String f2) {
this.f1 = f1;
this.f2 = f2;
}
int f1() { return f1;}
String f2() { return f2; }
}
public static void main(String[] args) {
List<Element> elements = new ArrayList<>();
elements.add(new Element(100, "Alice"));
elements.add(new Element(200, "Bob"));
elements.add(new Element(100, "Charles"));
elements.add(new Element(300, "Dave"));
elements.stream()
.collect(Collectors.groupingBy(
Element::f1,
Collectors.mapping(Element::f2, Collectors.toList())
))
.forEach((f1, f2) -> System.out.println("{"+f1.toString() + ", value="+f2+"}"));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12556 次 |
| 最近记录: |