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);
或
Multimap<Object, WithKey> m = ArrayListMultimap.create();
for (WithKey w : Iterables.concat(as, bs)) m.put(w.key(), w);
在使用多重映射之前(或在迭代多重映射条目时),您必须检查不变量,例如可能只有 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;
}
}
输出是:
{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);
输出((a,b) 是元组语法):
{1=(A{k=1, v=a},B{k=1, v=2}), 3=(A{k=3, v=c},B{k=3, v=6})}