2015-03-27 2 views
2

Давайте рассмотрим два arraylists.И/ИЛИ операции над списками в Java

ArrayList<Integer> list1 = new ArrayList<Integer>(); 
list1.add(1); 
list1.add(2); 
list1.add(3); 

ArrayList<Integer> list2 = new ArrayList<Integer>(); 
list2.add(3); 
list2.add(4); 
list2.add(5); 

Я хочу выполнить AND и OR между этими списками. Например, здесь, когда я выполняю И операция b/w list1 & list2 output должен быть списком, содержащим только 3 при выполнении ИЛИ операции b/w list1 & list2 output должен быть списком, содержащим 1,2,3,4 , 5 (не 3 повторяющихся дважды).

Есть ли возможность на Java реализовать этот сценарий? Можем ли мы использовать Java 8 Streams в этом случае? Пожалуйста, дайте мне наиболее эффективный способ получить ответ.

+0

Вы имеете в виду * пересечение множеств * и * объединение множеств *. Попробуйте использовать наборы. – khelwood

+1

@khelwood он попросил списки –

+0

@pivovarit Это не значит, что использование наборов не будет частью решения его проблемы. – khelwood

ответ

5

Используя поток API:

List<Integer> union = Stream.concat(list1.stream(), list2.stream()) 
          .distinct() 
          .collect(Collectors.toList()); 

List<Integer> intersection = list1.stream() 
            .filter(list2::contains) 
            .collect(Collectors.toList()); 

Без потока API:

List<Integer> intersection = new ArrayList<>(list1); 
intersection.retainAll(list2); 

List<Integer> union = new ArrayList<>(list1); 
List<Integer> toAdd = new ArrayList<>(list2); 
toAdd.removeAll(list1); // avoid duplicates 
union.addAll(toAdd); 
2

Чтобы избежать дубликатов, вам необходимо использовать Set s. Тогда речь идет только об использовании addAll(), removeAll() и retainAll() операций.

+0

Дайте мне код. Также мы можем использовать Streams здесь –

+4

@DeepakShajan _ «Дайте мне код» _ Я думаю, вы не знаете о том, как работает SO ... Попробуйте немного подумать, этот ответ уже дает вам решение. –

+0

@AlexisC .: Я хочу знать, как он подошел к вопросу, это может быть понято только кодом. –

1

Если вы действительно настаивают на Streams, вот что вы можете сделать:

Для И, вы можете сделать:

List<Integer> AND = list1.stream() 
         .filter(list2:contains) 
         .collect(Collectors.toList()); 

Для ИЛИ, вы можете сделать:

List<Integer> OR = Arrays.asList(list1, list2) 
         .stream() 
         .flatMap(List::stream) 
         .distinct() 
         .collect(Collectors.toList()); 

или даже лучше, как это было предложено @Alexis C. и вдохновленный @aioobe:

List<Integer> OR = Stream.concat(list1.stream(), list2.stream()) 
         .distinct() 
         .collect(Collectors.toList()); 
+2

.... или 'Stream.concat (list1.stream(), list2.stream()). Collect (toSet())' –

+0

Могу ли я добавить его в ответ? :) –

+0

Конечно, не стесняйтесь :-) –

1

Это может быть полезно:

Set<Integer> orSet = new HashSet<Integer>(); 
    orSet.addAll(list); 
    orSet.addAll(list1); 
    List<Integer> orList = new ArrayList<Integer>(orSet); 
    List<Integer> andList = new ArrayList<Integer>(); 
    int i=0; 
    Iterator<Integer> itr = list.iterator(); 
    while(itr.hasNext()){ 
     int v = itr.next(); 
     if(list1.contains(v)){ 
      andList.add(v); 
     } 
    } 

    System.out.println(orList); 
    System.out.println(andList); 
+0

Не нужно использовать 'Iterator' вручную (начиная с Java 5), ​​просто перебирайте с помощью' for (Integer v: list) ... '. Кроме того, вам не нужно повторять тип коллекций: 'Set orSet = new HashSet <>();', 'Список orList = новый ArrayList <> (orSet);' и т. Д. (Так как Java 7). Когда вы отвечаете на конкретный Java-вопрос, вы должны это рассмотреть. И обратите внимание, что 'HashSet' не имеет гарантий поручения и может быть непригодным для слияния« Список », вместо этого используйте« LinkedHashSet »... – Holger