Пересечение списка в java
У меня есть два ArrayList<Integer>
следующим образом:
оригинал: 12, 16, 17, 19, 101
: 16, 19, 107, 108, 109
Я хочу сделать пересечение/объединение в этих списках, чтобы в итоге у меня было два списка:
Добавить: 108,109,107
удалить: 12, 17, 101
Длина исходного и выбранного списков варьируется, и каждый может быть больше/меньше другого
Ответы
Ответ 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);
}