Intersection et union des ArrayLists en Java

Y a-t-il des méthodes pour le faire? Je cherchais mais je n’en trouvais pas.

Une autre question: j’ai besoin de ces méthodes pour pouvoir filtrer les fichiers. Certains sont des filtres AND et d’autres sont des filtres OR (comme dans la théorie des ensembles), donc je dois filtrer en fonction de tous les fichiers et des listes de tableaux unite / intersects contenant ces fichiers.

Dois-je utiliser une structure de données différente pour stocker les fichiers? Y a-t-il autre chose qui pourrait offrir un meilleur temps d’exécution?

Voici une implémentation simple sans utiliser de bibliothèque tierce. L’avantage principal sur retainAll , removeAll et addAll est que ces méthodes ne modifient pas l’entrée des listes d’origine dans les méthodes.

 public class Test { public static void main(Ssortingng... args) throws Exception { List list1 = new ArrayList(Arrays.asList("A", "B", "C")); List list2 = new ArrayList(Arrays.asList("B", "C", "D", "E", "F")); System.out.println(new Test().intersection(list1, list2)); System.out.println(new Test().union(list1, list2)); } public  List union(List list1, List list2) { Set set = new HashSet(); set.addAll(list1); set.addAll(list2); return new ArrayList(set); } public  List intersection(List list1, List list2) { List list = new ArrayList(); for (T t : list1) { if(list2.contains(t)) { list.add(t); } } return list; } } 

Collection (donc ArrayList aussi) a:

 col.retainAll(otherCol) // for intersection col.addAll(otherCol) // for union 

Utilisez une implémentation List si vous acceptez les répétitions, une implémentation Set si vous ne le faites pas:

 Collection col1 = new ArrayList(); // {a, b, c} // Collection col1 = new TreeSet(); col1.add("a"); col1.add("b"); col1.add("c"); Collection col2 = new ArrayList(); // {b, c, d, e} // Collection col2 = new TreeSet(); col2.add("b"); col2.add("c"); col2.add("d"); col2.add("e"); col1.addAll(col2); System.out.println(col1); //output for ArrayList: [a, b, c, b, c, d, e] //output for TreeSet: [a, b, c, d, e] 

Cet article est assez ancien, mais néanmoins, c’était le premier qui apparaissait sur Google lors de la recherche de ce sujet.

Je veux faire une mise à jour en utilisant les stream Java 8 faisant (essentiellement) la même chose en une seule ligne:

 List intersect = list1.stream() .filter(list2::contains) .collect(Collectors.toList()); List union = Stream.concat(list1.stream(), list2.stream()) .distinct() .collect(Collectors.toList()); 

Si quelqu’un a une solution meilleure / plus rapide, faites-le moi savoir, mais cette solution est une belle solution qui peut être facilement incluse dans une méthode sans append une classe / méthode d’assistance inutile et garder la lisibilité.

 list1.retainAll(list2) - is intersection 

union sera removeAll , puis addAll .

Trouvez plus dans la documentation de collection (ArrayList est une collection) http://download.oracle.com/javase/1.5.0/docs/api/java/util/Collection.html

Unions et intersections définies uniquement pour les ensembles, pas les listes. Comme vous l’avez mentionné.

Vérifiez la bibliothèque de goyave pour les filtres. La goyave fournit également de véritables intersections et unions

  static  Sets.SetViewunion(Set< ? extends E> set1, Set< ? extends E> set2) static  Sets.SetView intersection(Set set1, Set< ?> set2) 

Vous pouvez utiliser CollectionUtils partir de apache commons .

La solution marquée n’est pas efficace. Il a une complexité temporelle O (n ^ 2). Ce que nous pouvons faire est de sortinger les deux listes et d’exécuter un algorithme d’intersection comme celui ci-dessous.

 private static ArrayList interesect(ArrayList f, ArrayList s) { ArrayList res = new ArrayList(); int i = 0, j = 0; while (i != f.size() && j != s.size()) { if (f.get(i) < s.get(j)) { i ++; } else if (f.get(i) > s.get(j)) { j ++; } else { res.add(f.get(i)); i ++; j ++; } } return res; } 

Celui-ci a une complexité de O (n log n + n) qui est dans O (n log n). L’union se fait de la même manière. Assurez-vous de faire les modifications appropriées sur les instructions if-elseif-else.

Vous pouvez également utiliser des iterators si vous voulez (je sais qu’ils sont plus efficaces en C ++, je ne sais pas si cela est également vrai en Java).

Je pense que vous devriez utiliser un Set pour contenir les fichiers si vous voulez faire une intersection et une union sur eux. Vous pouvez ensuite utiliser la classe Ensembles de goyave pour faire également l’ union , l’ intersection et le filtrage par un Predicate . La différence entre ces méthodes et les autres suggestions est que toutes ces méthodes créent des vues paresseuses de l’union, de l’intersection, etc. des deux ensembles. Apache Commons crée une nouvelle collection et copie les données. retainAll modifie l’une de vos collections en en supprimant des éléments.

Voici comment vous pouvez faire une intersection avec des stream (rappelez-vous que vous devez utiliser java 8 pour les stream):

 List fooList1 = new ArrayList<>(Arrays.asList(new foo(), new foo())); List fooList2 = new ArrayList<>(Arrays.asList(new foo(), new foo())); fooList1.stream().filter(f -> fooList2.contains(f)).collect(Collectors.toList()); 

Un exemple pour les listes avec différents types. Si vous avez une relation entre foo et bar et que vous pouvez obtenir un object-barre de foo, vous pouvez modifier votre stream:

 List fooList = new ArrayList<>(Arrays.asList(new foo(), new foo())); List barList = new ArrayList<>(Arrays.asList(new bar(), new bar())); fooList.stream().filter(f -> barList.contains(f.getBar()).collect(Collectors.toList()); 
  • keepAll modifiera votre liste
  • Guava n’a pas d’API pour la liste (uniquement pour l’ensemble)

J’ai trouvé ListUtils très utile pour ce cas d’utilisation.

Utilisez ListUtils from org.apache.commons.collections si vous ne souhaitez pas modifier la liste existante.

ListUtils.intersection(list1, list2)

En Java 8, j’utilise des méthodes d’aide simples comme celle-ci:

 public static  Collection getIntersection(Collection coll1, Collection coll2){ return Stream.concat(coll1.stream(), coll2.stream()) .filter(coll1::contains) .filter(coll2::contains) .collect(Collectors.toSet()); } public static  Collection getMinus(Collection coll1, Collection coll2){ return coll1.stream().filter(not(coll2::contains)).collect(Collectors.toSet()); } public static  Predicate not(Predicate t) { return t.negate(); } 

Je travaillais également sur la situation similaire et je suis arrivé ici pour chercher de l’aide. J’ai fini par trouver ma propre solution pour les tableaux. ArrayList AbsentDates = new ArrayList (); // va stocker Array1-Array2

Note: Publiez ceci si cela peut aider quelqu’un à accéder à cette page pour de l’aide.

 ArrayList AbsentDates = new ArrayList();//This Array will store difference public void AbsentDays() { findDates("April", "2017");//Array one with dates in Month April 2017 findPresentDays();//Array two carrying some dates which are subset of Dates in Month April 2017 for (int i = 0; i < Dates.size(); i++) { for (int j = 0; j < PresentDates.size(); j++) { if (Dates.get(i).equals(PresentDates.get(j))) { Dates.remove(i); } } AbsentDates = Dates; } System.out.println(AbsentDates ); } 

Vous pouvez utiliser commons-collections4 CollectionUtils

 Collection collection1 = Arrays.asList(1, 2, 4, 5, 7, 8); Collection collection2 = Arrays.asList(2, 3, 4, 6, 8); Collection intersection = CollectionUtils.intersection(collection1, collection2); System.out.println(intersection); // [2, 4, 8] Collection union = CollectionUtils.union(collection1, collection2); System.out.println(union); // [1, 2, 3, 4, 5, 6, 7, 8] Collection subtract = CollectionUtils.subtract(collection1, collection2); System.out.println(subtract); // [1, 5, 7] 

Si les objects de la liste sont gérables (c’est-à-dire qu’ils ont un hashCode et une fonction égaux), l’approche la plus rapide entre les tables est d’environ. taille> 20 consiste à construire un HashSet pour la plus grande des deux listes.

 public static  ArrayList intersection(Collection a, Collection b) { if (b.size() > a.size()) { return intersection(b, a); } else { if (b.size() > 20 && !(a instanceof HashSet)) { a = new HashSet(a); } ArrayList result = new ArrayList(); for (T objb : b) { if (a.contains(objb)) { result.add(objb); } } return result; } } 

Solution finale:

 //all sorted items from both public  List getListReunion(List list1, List list2) { Set set = new HashSet(); set.addAll(list1); set.addAll(list2); return new ArrayList(set); } //common items from both public  List getListIntersection(List list1, List list2) { list1.retainAll(list2); return list1; } //common items from list1 not present in list2 public  List getListDifference(List list1, List list2) { list1.removeAll(list2); return list1; } 

Tout d’abord, je copie toutes les valeurs des tableaux dans un seul tableau, puis je supprime les valeurs en double dans le tableau. La ligne 12, expliquant si le même nombre se produit plus que le temps, met alors une valeur supplémentaire dans la position “j”. À la fin, traversez depuis le début et vérifiez si la même valeur de déchet se produit, puis annulez.

 public class Union { public static void main(Ssortingng[] args){ int arr1[]={1,3,3,2,4,2,3,3,5,2,1,99}; int arr2[]={1,3,2,1,3,2,4,6,3,4}; int arr3[]=new int[arr1.length+arr2.length]; for(int i=0;i 

Si vous aviez vos données dans les ensembles, vous pourriez utiliser la classe Sets de goyave.

Si le nombre correspond à ce que je vérifie, il se produit la première fois ou non avec l’aide de “indexOf ()” si le numéro correspond à la première fois, puis imprime et enregistre dans la chaîne. t imprimer car en raison de “indexOf ()”, la condition sera fausse.

 class Intersection { public static void main(Ssortingng[] args) { Ssortingng s=""; int[] array1 = {1, 2, 5, 5, 8, 9, 7,2,3512451,4,4,5 ,10}; int[] array2 = {1, 0, 6, 15, 6, 5,4, 1,7, 0,5,4,5,2,3,8,5,3512451}; for (int i = 0; i < array1.length; i++) { for (int j = 0; j < array2.length; j++) { char c=(char)(array1[i]); if(array1[i] == (array2[j])&&s.indexOf(c)==-1) { System.out.println("Common element is : "+(array1[i])); s+=c; } } } } 

}