Как вычесть коллекции с интерфейсом Comparator вместо переопределения равных - PullRequest
5 голосов
/ 08 сентября 2011

Я хочу вычислить различия между коллекциями.При использовании CollectionUtils.subtract () для пользовательского сравнения мне нужно переопределить метод equals () объекта.Но что, если мне нужно сравнить коллекции объектов одного типа, но с другим критерием сравнения?А как насчет интерфейса Comparator, он, кажется, идеально подходит здесь?AFAIK Comparator в основном используется для сортировки.Разве нет метода, который использует компараторы для вычитания?

Ответы [ 2 ]

4 голосов
/ 08 сентября 2011
static <Type> Collection<Type> subtract(Collection<Type> a, Collection<Type> b, Comparator<Type> c) {
    Set<Type> subtrahend = new TreeSet<Type>(c);
    subtrahend.addAll(b);
    Collection<Type> result = new ArrayList<Type>();
    for (Type item: a) {
        if (!subtrahend.contains(item)) result.add(item);
    }
    return result;
}

Набор деревьев subtrahent необязателен, но улучшит производительность для больших b.

2 голосов
/ 08 сентября 2011

Если у вас есть ArrayList, многократное удаление может оказаться более дорогим, чем получение копии.

List<Type> list = /* ArrayList */
Set<Type> toRemove = /* HashSet */
List<Type> copy = new ArrayList<Type>(list.size());
for(Type t: list)
  if(!toRemove.contains(t))
    copy.add(t);
list = copy;

Лично я бы использовал цикл. Вероятно, он будет короче и четче.

Collection<Type> collection =

for(Iterator<Type> i=collection.iterator(); i.hasNext();)
   if (i.next() is to be removed)
       i.remove();

Причина, по которой итератор используется явно, состоит в том, чтобы использовать Iterator.remove (), который избегает исключения ConcurrentModificationException. Другой способ избежать этого - использовать копию коллекции, которая может быть предпочтительнее.

for(Type t : new ArrayList<Type>(collection))
   if (t is to be removed)
       collection.remove(t);

Это не так хорошо, но может работать достаточно хорошо.

...