Пересечение различных типов коллекций - PullRequest
0 голосов
/ 26 августа 2011

У меня 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.Что я могу сделать, чтобы улучшить это, с точки зрения производительности и / или ресурсов?

Ответы [ 3 ]

1 голос
/ 26 августа 2011

Не могли бы вы поместить 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>, а не Map,но мне нравится симметрия.

1 голос
/ 26 августа 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();
    }
}

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

0 голосов
/ 26 августа 2011

Вы можете использовать класс Guava Collections2 для 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());
            }
        });
...