Как пересечь несколько наборов?

У меня есть этот список:

private List<Set<Address>> scanList;

Итак, мой список содержит несколько сканирований, как вы можете видеть. После каждого сканирования я добавляю новый набор в список.

После того, как все сканирования завершены, я хотел бы взять только те адреса, которые встречаются в каждом наборе, и поместить их в:

private List<Address> addresses;

Что-то подобное уже существует в Set/TreeSet/HashSet?

РЕДАКТИРОВАТЬ: после ответов, keepAll() является правильным методом. Спасибо. Вот источник:

Set<Address> addressCross = scanList.get(0);
for (int i = 1; i < scanList.size(); i++) {
    addressCross.retainAll(scanList.get(i));
}   
for (Address address : addressCross) {
    addresses.add(address);
}

person vale4674    schedule 24.10.2010    source источник


Ответы (3)


См. «сохранить все ()».

person Lavir the Whiolet    schedule 24.10.2010

вы можете использовать retainAll(Collection<?> c), посмотрите здесь

Примечание: эта операция называется пересечение.

Чтобы преобразовать его в List, вы можете использовать метод addAll(Collection<? extends E> c), который должен работать со всеми типами контейнеров.

eg:

ArrayList<Address> list = new ArrayList<Address>();
list.addAll(yourSet);
person Jack    schedule 24.10.2010

С помощью Guava это можно сделать следующим образом:

Set<Address> intersection = scanList.get(0);
for (Set<Address> scan : scanList.subList(1, scanList.size())) {
  intersection = Sets.intersection(intersection, scan);
}
List<Address> addresses = Lists.newArrayList(intersection);

Это создает представление пересечения всех наборов в scanList, а затем копирует адреса в пересечении в List. Конечно, вам нужно убедиться, что в вашем scanList есть хотя бы один элемент.

person ColinD    schedule 24.10.2010
comment
Остерегаться! По словам Луи Вассермана, Sets.union() имеет плохие результаты более чем в 2 сетах. Я считаю, что то же самое верно и для Sets.intersection() (поскольку оба метода возвращают представления). - person Gili; 01.09.2015
comment
@Gili: В целом это верно, хотя это смягчается тем фактом, что набор пересечений копируется в конце, а это означает, что стоимость вложенных наборов возникает только там. Проблема с вложенными наборами представлений усугубится, если вы затем передадите набор какому-то другому коду, который может выполнять много contains вызовов для него. - person ColinD; 01.09.2015
comment
Я пришел к этому обсуждению немного поздно, но разве это решение не предполагает, что первый набор содержит ключевые элементы. Например, рассмотрим первый набор с целыми числами (11,12), второй с (1,3,4,5,6) и так далее. Когда я кодирую это, окончательный набор множественных пересечений пуст! - person Graham Seed; 28.07.2017
comment
@ user25029: Цель состоит в том, чтобы создать список, содержащий только те элементы, которые появляются во всех наборах. Таким образом, если во входных данных есть пара множеств, не содержащих одинаковых элементов (т. е. их пересечение пусто), конечный результат должен быть пустым. - person ColinD; 29.07.2017