web-dev-qa-db-fra.com

Intersection efficace de deux listes <String> en Java?

La question est simple:

J'ai deux liste

List<String> columnsOld = DBUtils.GetColumns(db, TableName);
List<String> columnsNew = DBUtils.GetColumns(db, TableName);

Et je dois obtenir l'intersection de ceux-ci. Y a-t-il un moyen rapide d'y parvenir?

55
Pentium10

Vous pouvez utiliser retainAll method:

columnsOld.retainAll (columnsNew);
106
Roman

Dans la mesure où KeepAll ne touche pas la collection d'arguments, ce serait plus rapide:

List<String> columnsOld = DBUtils.GetColumns(db, TableName); 
List<String> columnsNew = DBUtils.GetColumns(db, TableName); 

for(int i = columnsNew.size() - 1; i > -1; --i){
    String str = columnsNew.get(i);
    if(!columnsOld.remove(str))
        columnsNew.remove(str);
}

L'intersection sera les valeurs laissées dans les colonnesNouveau. Supprimer les valeurs déjà comparées de columnOld réduira le nombre de comparaisons nécessaires.

18
bjornhol

Utilisation de goyave:

Sets.intersection(Sets.newHashSet(setA), Sets.newHashSet(setB))

Google Guava Library

16
Sergii Shevchyk

Que diriez-vous

private List<String> intersect(List<String> A, List<String> B) {
    List<String> rtnList = new LinkedList<>();
    for(String dto : A) {
        if(B.contains(dto)) {
            rtnList.add(dto);
        }
    }
    return rtnList;
}
8
Gigas

Il existe une manière sympa avec les flux qui peuvent le faire dans une ligne de code et vous pouvez utiliser deux listes qui ne sont pas du même type, ce qui n’est pas possible avec la méthode includesAll:

columnsOld.stream().filter(c -> columnsNew.contains(c)).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 objet bar de foo, vous pouvez modifier votre flux:

List<foo> fooList = new ArrayList<>(Arrays.asList(new foo(), new foo()));
List<bar> barList = new ArrayList<>(Arrays.asList(new bar(), new bar()));

fooList.stream().filter(f -> barList.contains(f.getBar()).collect(Collectors.toList());
2
Deutro

Si vous mettez la deuxième liste dans un ensemble, dites HashSet. Et parcourez simplement la première liste en recherchant la présence sur le plateau et en la supprimant, votre première liste comportera éventuellement l'intersection dont vous avez besoin . Elle sera bien plus rapide que retenue ou contient sur une liste . L'accent est mis ici sur l'utilisation d'un ensemble au lieu d'une liste. Les recherches sont O (1) . FirstList.retainAll (new HashSet (secondList)) fonctionnera également.

1
Ravi Sanwal

utilisez org.Apache.commons.collections4.ListUtils # intersection

0
Dheeraj Sachan

utiliser retenueAll si ne se soucie pas des occurrences, sinon utiliser N.intersection

a = N.asList(12, 16, 16, 17, 19);
b = N.asList(16, 19, 107);
a.retainAll(b); // [16, 16, 19]
N.println(a);

a = N.asList(12, 16, 16, 17, 19);
b = N.asList(16, 19, 107);
a = N.intersect(a, b);
N.println(a); // [16, 19]

N est une classe d'utilitaires dans AbacusUtil

0
user_3380739