Пересекать коллекции разного типа

У меня есть Collection<A> ca и Collection<B> cb, A и B, не использующие общий интерфейс, но каждый из которых имеет свойство String, называемое something. Мне нужно отфильтровать ca и сохранить только те элементы, которые имеют «соответствующее» значение в cb.

К сожалению, создание общего интерфейса для A и B в соответствии с этот вопрос/ответ не подходит.

сейчас я делаю

Iterator<A> it = ca.iterator();
while ( it.hasNext() ) {
    A a = it.next();
    if ( !cb.contains(new B(a.getSomething(), ... <known stuff>) )
        it.remove;
}

используя тот факт, что я знаю, что делает B.equals. Могу ли я что-нибудь сделать, чтобы улучшить это с точки зрения производительности и/или ресурсов?


person Gustav Barkefors    schedule 25.08.2011    source источник
comment
Было бы полезно, если бы люди понимали, почему создание общего интерфейса невозможно. Например, у вас нет доступа для изменения класса A или класса B?   -  person Ben Hocking    schedule 26.08.2011
comment
@Ben: Да, это так просто. Я не могу коснуться кода, который дает мне as. (ВЛОГ :) )   -  person Gustav Barkefors    schedule 26.08.2011


Ответы (3)


Не могли бы вы поместить As и B в карты с ключом String? Затем вы можете просто использовать Collection.retainAll() пару раз:

Map<String, A> as = new HashMap<String, A>;
for (A a: ca) as.put(a.getSomething(), a);
Map<String, B> bs = new HashMap<String, B>;
for (B b: cb) bs.put(b.getSomething(), b);
as.keySet().retainAll(bs.keySet());
ca.retainAll(as.values());

Немного безумно, но вот.

bs может быть Set<String>, а не картой, но мне нравится симметрия.

person Tom Anderson    schedule 25.08.2011
comment
Этот подход прекрасно работает, тем более, что оказалось, что соответствующие Map<A> были легко доступны с самого начала. - person Gustav Barkefors; 31.08.2011

Можете ли вы подумать о создании новых объектов-оболочек?

interface Holder {
    Object getThing(); //or a primative

class HolderA implements Holder {
    private A a;

    public HolderA(A _a) {
        a = _a;
    }

    public Object getThing() {
        return a.getSomething();
    }
}

class HolderB implements Holder {
    private B b;

    public HolderB(B _b) {
        b = _b;
    }

    public Object getThing() {
        return b.getSomething();
    }
}

Я думаю, вы должны быть в состоянии сравнить эти два объекта.

person nicholas.hauschild    schedule 25.08.2011
comment
Да, может быть вариант. Сомневаюсь, что в конце концов это действительно упростится... Я посмотрю на это. +1 - person Gustav Barkefors; 26.08.2011
comment
Однако он кажется менее «хакерским», поскольку вместо этого используются принципы объектно-ориентированного подхода. - person nicholas.hauschild; 26.08.2011

Вы можете использовать Коллекции гуавы2 к transform и filter следующим образом:

Collection<A> as = ...;
Collection<B> bs = ...;

final Collection<String> b_somethings = 
    Collections2.transform(
        bs, 
        new Function<B, String>() {
            public String apply(B input) {
                return input.getSomething();
            }   
        });

Collection<A> filtered_as = 
    Collections2.filter(
        as, 
        new Predicate<A>() {
            public boolean apply(A input) {
                return b_somethings.contains(input.getSomething());
            }
        });
person beny23    schedule 25.08.2011