如何将列表A,B转换为带有番石榴的元组的键控映射

ger*_*ges 5 java functional-programming guava

我很抱歉,如果这个问题是一个重复的,搜索是困难的,因为我是不确定的就是我试图完成正确的名称.最简单的解释是

List<A>, List<B> into Map<Key, Tuple<A,B>> where A.Key matched B.Key
Run Code Online (Sandbox Code Playgroud)

澄清一下:我有一个共享密钥的A对象和B对象的列表.我想那么这两个列表关联到一个地图,当密钥匹配到地图的关键,而元组A,B.

我已经在脑子里玩了很多关于如何做到这一点的想法,但大多数人都觉得我觉得我误用了这个库(比如Maps.uniqueIndex和Iterables.transform).谁能指出我正确的方向?

Tho*_*ung 6

Guava中没有元组(对等)实现.(这是另一个讨论,如果在Java中实现元组是个好主意.)我建议的自然映射是使用Multimap:

List<A> as = Lists.newArrayList(new A(1, "a"), new A(3, "c"), new A(2, "b"));
List<B> bs = Lists.newArrayList(new B(1, 2), new B(3, 6), new B(5, 10));

Function<WithKey, Object> toKey = new Function<WithKey, Object>() {
    @Override public Object apply(WithKey input) { return input.key(); }
};
ImmutableListMultimap<Object, AbstractWithKey> index = 
    Multimaps.index(Iterables.concat(as, bs), toKey);
Run Code Online (Sandbox Code Playgroud)

要么

Multimap<Object, WithKey> m = ArrayListMultimap.create();
for (WithKey w : Iterables.concat(as, bs)) m.put(w.key(), w);
Run Code Online (Sandbox Code Playgroud)

您必须在使用多图之前(或在迭代多图条目时)检查不变量,例如,可能只有A或B实例的键.(这不应该是性能问题,因为它可以通过Iterables.filter懒散地完成.)

一种类型的重复是另一个问题.您可以检查它们或使用HashMultimap忽略它们.您甚至可以构建一个带有约束集的多图,用于检查值是唯一的值(请参阅Multimaps.newSetMultimap(Map> map,Supplier> factory)Constraints.constrainedSet(Set set,Constraint constraint)).这具有快速失败的优点.

通过这些A和B实现:

interface WithKey {
    Object key();
}
abstract class AbstractWithKey implements WithKey {
    Object key;
    Object v;
    @Override public Object key() { return key; }
    @Override public String toString() { 
        return MoreObjects.toStringHelper(this).add("k", key).add("v", v).toString(); 
    }
}
class A extends AbstractWithKey {
    public A(int i, String v) { 
        key = i;
        this.v = v;
    } 
}
class B extends AbstractWithKey {
    public B(int i, int v) { 
        key = i;
        this.v = v;
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是:

{1 = [A {k = 1,v = a},B {k = 1,v = 2}],2 = [A {k = 2,v = b}],3 = [A {k = 3 ,v = c},B {k = 3,v = 6}],5 = [B {k = 5,v = 10}]}

更新:

如果必须最终使用元组实例,则可以转换Multimap.

Multimap<Object, WithKey> m = ArrayListMultimap.create(); 
for (WithKey w : Iterables.concat(as, bs)) m.put(w.key(), w);

Function<Collection<WithKey>, Tuple> f = 
    new Function<Collection<WithKey>, Tuple>(){
    @Override public Tuple apply(Collection<WithKey> input) {
        Iterator<WithKey> iterator = input.iterator();
        return new Tuple(iterator.next(), iterator.next());
    } };
Map<Object, Tuple> result = Maps.transformValues(m.asMap(), f);
Run Code Online (Sandbox Code Playgroud)

输出((a,b)是元组语法):

{1=(A{k=1, v=a},B{k=1, v=2}), 3=(A{k=3, v=c},B{k=3, v=6})}
Run Code Online (Sandbox Code Playgroud)