В 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 (Карта> карта, Поставщик> фабрика) и Constraints.constrainedSet (Установить набор, Ограничительное ограничение) ). Преимущество в том, что он быстро выходит из строя.
С этими реализациями 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})}