70 votes

Comment comparer l'égalité de listes de tableaux modernes Java?

J'ai deux listes de tableaux.

Comment puis-je facilement comparer l'égalité de ces avec Java 8 et ses caractéristiques, sans l'aide de bibliothèques externes? Je suis à la recherche d'un "mieux" (de niveau supérieur, plus court, plus efficace) de la solution de force brute ce type de code (code non testé, peuvent contenir des fautes de frappe, etc, pas le point de la question):

boolean compare(List<String[]> list1, List<String[]> list2) 
{
    // tests for nulls etc omitted
    if(list1.size() != list2.size()) {
       return false;
    }
    for(i=0; i<list1.size(); ++i) {
        if(!Arrays.equals(list1.get(i), list2.get(i))) {
            return false;
        }
    }
    return true;
}

Ou, si il n'y a pas plus belle façon, c'est une réponse valable.

Bonus: Si Java 9 offre une meilleure façon de le faire ce whaterver Java 8 peut offrir, n'hésitez pas à le mentionner.

Edit: Après avoir regardé les commentaires, et de voir comment cette question est devenue modérément chaud, je pense que le "mieux", il faudrait d'abord vérifier les longueurs de tous les tableaux, avant de vérifier le contenu du tableau, parce que cela a le potentiel pour trouver l'inégalité beaucoup plus rapide, si l'intérieur des tableaux sont longues.

52voto

khelwood Points 13552

L' for boucle, au moins peut être streamified, conduisant à:

return (list1.size()==list2.size() &&
        IntStream.range(0, list1.size())
                 .allMatch(i -> Arrays.equals(list1.get(i), list2.get(i)));

31voto

Babur Points 129

à l'aide de zip (qui provient de lambda b93) la fonction de http://stackoverflow.com/a/23529010/755183, le code pourrait ressembler à:

boolean match = a.size() == b.size() && 
                zip(a.stream(), b.stream(), Arrays::deepEquals).
                allMatch(equal -> equal)

mise à jour

afin de vérifier la taille de tableaux premier, puis le contenu de ce pourrait être une solution à envisager

final boolean match = a.size() == b.size() 
                   && zip(a.stream(), b.stream(), (as, bs) -> as.length == bs.length).
                      allMatch(equal -> equal)
                   && zip(a.stream(), b.stream(), Arrays::deepEquals).
                      allMatch(equal -> equal);

31voto

Dragan Bozanovic Points 3704

1) Solution basée sur Java 8 volets:

List<List<String>> first = list1.stream().map(Arrays::asList).collect(toList());
List<List<String>> second = list2.stream().map(Arrays::asList).collect(toList());
return first.equals(second);

2) solution Beaucoup plus simple (fonctionne en Java 5+):

return Arrays.deepEquals(list1.toArray(), list2.toArray());

3) au Sujet de votre nouvelle exigence (pour vérifier le contenu des tableaux de Chaîne longueur de la première), vous pourriez écrire un générique de la méthode d'assistance que ne l'égalité vérifier transformé listes:

<T, U> boolean equal(List<T> list1, List<T> list2, Function<T, U> mapper) {
    List<U> first = list1.stream().map(mapper).collect(toList());
    List<U> second = list2.stream().map(mapper).collect(toList());
    return first.equals(second);
}

Ensuite, la solution pourrait être:

return equal(list1, list2, s -> s.length)
    && equal(list1, list2, Arrays::asList);

15voto

ZouZou Points 23600

Vous pourriez utiliser un flux si les listes sont aléatoires des listes d'accès (de sorte qu'un appel à l' get rapide est généralement constante de temps) conduisant à:

//checks for null and size before
boolean same = IntStream.range(0, list1.size()).allMatch(i -> Arrays.equals(list1.get(i), list2.get(i)));

Cependant, vous pourriez donner comme paramètres des implémentations qui ne le sont pas (comme LinkedLists). Dans ce cas, le meilleur moyen est d'utiliser l'itérateur explicitement. Quelque chose comme:

boolean compare(List<String[]> list1, List<String[]> list2) {

    //checks for null and size

    Iterator<String[]> iteList1 = list1.iterator();
    Iterator<String[]> iteList2 = list2.iterator();

    while(iteList1.hasNext()) {
        if(!Arrays.equals(iteList1.next(), iteList2.next())) {
            return false;
        }
    }
    return true;
}

6voto

Vous pourriez diffuser sur une liste et de les comparer pour chaque élément de l'autre à l'aide d'un itérateur:

Iterator<String[]> it = list1.iterator();
boolean match = list1.size() == list2.size() &&
                list2.stream().allMatch(a -> Arrays.equals(a, it.next()));

À l'aide d'un itérateur à la place de l' get(index) méthode sur la première liste est mieux parce qu'il n'a pas d'importance si la liste est RandomAccess ou pas.

Note: ceci ne fonctionne qu'avec un séquentielle flux. À l'aide d'un courant parallèle va conduire à des résultats faux.


EDIT: Comme pour la question de la dernière édition, ce qui indique qu'il serait préférable de vérifier la longueur de chaque paire de tableaux à l'avance, je pense qu'il pourrait être atteint avec une légère modification de mon code précédent:

Iterator<String[]> itLength = list1.iterator();
Iterator<String[]> itContents = list1.iterator();

boolean match = 
        list1.size() == list2.size()
    && 
        list2.stream()
            .allMatch(a -> {
                String[] s = itLength.next();
                return s == null ? a == null :
                       a == null ? s == null :
                       a.length == s.length;
            })
    && 
        list2.stream()
            .allMatch(a -> Arrays.equals(a, itContents.next()));

Ici, je suis l'aide de deux itérateurs et suis streaming list2 deux fois, mais je ne vois pas d'autre moyen de vérifier toutes les longueurs avant de vérifier le contenu de la première paire de tableaux. Vérifiez pour des longueurs est null-sécuritaire, tout en vérifier le contenu est déléguée au Arrays.equals(array1, array2) méthode.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X