Подтвердить что ты не робот

Пересечение списка в java

У меня есть два ArrayList<Integer> следующим образом:

оригинал: 12, 16, 17, 19, 101

: 16, 19, 107, 108, 109

Я хочу сделать пересечение/объединение в этих списках, чтобы в итоге у меня было два списка:

Добавить: 108,109,107

удалить: 12, 17, 101

Длина исходного и выбранного списков варьируется, и каждый может быть больше/меньше другого

4b9b3361

Ответ 1

List<Integer> original = Arrays.asList(12,16,17,19,101);
List<Integer> selected = Arrays.asList(16,19,107,108,109);

ArrayList<Integer> add = new ArrayList<Integer>(selected);
add.removeAll(original);
System.out.println("Add: " + add);

ArrayList<Integer> remove = new ArrayList<Integer>(original);
remove.removeAll(selected);
System.out.println("Remove: " + remove);

Вывод:

Add: [107, 108, 109]
Remove: [12, 17, 101]

Использует метод удаления removeAll. См. javadocs.

Ответ 2

В качестве альтернативы вы можете использовать CollectionUtils из библиотеки общин Apache. Он имеет статические методы пересечения, union и вычесть, подходящие для вашего случая.

Ответ 3

Пересечение: original.retainAll(selected).

После этого оригинал будет содержать только элементы, присутствующие в обеих коллекциях. Возвращает true, если что-то изменилось.

ВНИМАНИЕ: этот метод очень медленный для больших коллекций

Ответ 4

Для операций пересечения и объединения естественный тип коллекции представляет собой набор, а не список, его также более эффективно использовать.

Ответ 5

Использование библиотеки Guava:

List<Integer> listA = Lists.newArrayList(12,16,17,19,101);
List<Integer> listB = Lists.newArrayList(16,19,107,108,109);
Set<Integer> intersection = Sets.intersection(Sets.newHashSet(listA), Sets.newHashSet(listB));
listA.removeAll(intersection);
listB.removeAll(intersection);

Ответ 6

 List<Integer> original;
 List<Integer> selected;

 List<Integer> add = new ArrayList<Integer>(selected);
 add.removeAll(original);

 List<Integer> remove = new ArrayList<Integer>(original);
 remove.removeAll(selected);

Будьте осторожны с граничными случаями вокруг повторяющихся элементов. Следует ли уважать кардинальность? Как и в, если я имел 5, 6 изначально и 5, 5, 6 после, должен добавить be 5? Вышеизложенное работает лучше с Set s, так как у них нет дубликатов (плюс contains() поиск быстрее, поскольку они индексируются содержащимися в них данными).

Ответ 7

Доступна новая библиотека underscore-java. Это может сделать разницу и пересечение для списков и массивов. Живой пример.

Пример кода:

List<Integer> original = Arrays.asList(12, 16, 17, 19, 101);
List<Integer> selected = Arrays.asList(16, 19, 107, 108, 109);
List<Integer> add = U.difference(selected, U.intersection(original, selected));
List<Integer> remove = U.difference(original, selected);

Ответ 8

Вот функция, чтобы найти пересечение различных коллекций (более 2) -

public static <T, C extends Collection<T>> C findIntersection(C newCollection,
                                                            Collection<T>... collections) {
  boolean first = true;
  for (Collection<T> collection : collections) {
      if (first) {
          newCollection.addAll(collection);
          first = false;
      } else {
          newCollection.retainAll(collection);
      }
  }
  return newCollection;
}

Использование -

public static void main(String[] args) {
  List<Integer> l1 = List.of(1, 3, 5, 7, 9, 11, 13);
  List<Integer> l2 = List.of(1, 2, 3, 5, 8, 13);
  List<Integer> l3 = List.of(2, 3, 5, 7, 11, 13);
  Set<Integer> intersection = findIntersection(new HashSet<>(), l1, l2, l3);
  System.out.println(intersection);
 }