Java compare deux listes


92

J'ai deux listes (pas des listes java, vous pouvez dire deux colonnes)

Par exemple

**List 1**            **Lists 2**
  milan                 hafil
  dingo                 iga
  iga                   dingo
  elpha                 binga
  hafil                 mike
  meat                  dingo
  milan
  elpha
  meat
  iga                   
  neeta.peeta    

J'aimerais une méthode qui renvoie le nombre d'éléments identiques. Pour cet exemple, il devrait être 3 et il devrait me renvoyer des valeurs similaires de liste et de valeurs différentes également.

Dois-je utiliser hashmap si oui, quelle méthode pour obtenir mon résultat?

Veuillez aider

PS: Ce n'est pas une mission scolaire :) Donc si vous me guidez, cela suffira


Veuillez suggérer une structure de données, la liste n'est pas une liste java ou un hashmap ou une structure de données
user238384

1
Pensez à ce que vous devez faire dans des cas exceptionnels. Les listes peuvent-elles contenir deux fois la même valeur? Si tel est le cas, si «dingo» figure deux fois dans les deux listes, est-ce que cela compte comme deux éléments en commun ou un seul?
JavadocMD

Pouvez-vous modifier l'une des listes?
Anthony Forloney

comment éditer ?? Oui, chaque liste peut contenir des valeurs similaires plusieurs fois
user238384

Il devrait y avoir un petit lien d' édition juste après la question, sous les balises.
OscarRyz

Réponses:


159

ÉDITER

Voici deux versions. Une utilisation ArrayListet une autre utilisationHashSet

Comparez-les et créez votre propre version à partir de là, jusqu'à ce que vous obteniez ce dont vous avez besoin.

Cela devrait suffire à couvrir:

PS: Ce n'est pas une mission scolaire :) Donc si vous me guidez, cela suffira

une partie de votre question.

continuer avec la réponse originale:

Vous pouvez utiliser un java.util.Collection et / ou java.util.ArrayListpour cela.

La méthode retentionAll effectue les opérations suivantes:

Conserve uniquement les éléments de cette collection qui sont contenus dans la collection spécifiée

voir cet exemple:

import java.util.Collection;
import java.util.ArrayList;
import java.util.Arrays;

public class Repeated {
    public static void main( String  [] args ) {
        Collection listOne = new ArrayList(Arrays.asList("milan","dingo", "elpha", "hafil", "meat", "iga", "neeta.peeta"));
        Collection listTwo = new ArrayList(Arrays.asList("hafil", "iga", "binga", "mike", "dingo"));

        listOne.retainAll( listTwo );
        System.out.println( listOne );
    }
}

ÉDITER

Pour la deuxième partie (valeurs similaires), vous pouvez utiliser la méthode removeAll :

Supprime tous les éléments de cette collection qui sont également contenus dans la collection spécifiée.

Cette deuxième version vous donne également les valeurs similaires et gère les répétitions (en les supprimant).

Cette fois, le Collectionpourrait être un Setau lieu d'un List(la différence est que l'ensemble ne permet pas de valeurs répétées)

import java.util.Collection;
import java.util.HashSet;
import java.util.Arrays;

class Repeated {
      public static void main( String  [] args ) {

          Collection<String> listOne = Arrays.asList("milan","iga",
                                                    "dingo","iga",
                                                    "elpha","iga",
                                                    "hafil","iga",
                                                    "meat","iga", 
                                                    "neeta.peeta","iga");

          Collection<String> listTwo = Arrays.asList("hafil",
                                                     "iga",
                                                     "binga", 
                                                     "mike", 
                                                     "dingo","dingo","dingo");

          Collection<String> similar = new HashSet<String>( listOne );
          Collection<String> different = new HashSet<String>();
          different.addAll( listOne );
          different.addAll( listTwo );

          similar.retainAll( listTwo );
          different.removeAll( similar );

          System.out.printf("One:%s%nTwo:%s%nSimilar:%s%nDifferent:%s%n", listOne, listTwo, similar, different);
      }
}

Production:

$ java Repeated
One:[milan, iga, dingo, iga, elpha, iga, hafil, iga, meat, iga, neeta.peeta, iga]

Two:[hafil, iga, binga, mike, dingo, dingo, dingo]

Similar:[dingo, iga, hafil]

Different:[mike, binga, milan, meat, elpha, neeta.peeta]

S'il ne fait pas exactement ce dont vous avez besoin, cela vous donne un bon départ afin que vous puissiez gérer à partir d'ici.

Question pour le lecteur: Comment incluriez-vous toutes les valeurs répétées?


@Oscar, Ma pensée exacte, mais je ne savais pas si nous aurions pu modifier le contenu de listOne, mais +1 quand même!
Anthony Forloney

@poygenelubricants qu'entendez-vous par types bruts et non génériques? Pourquoi pas?
OscarRyz

Oscar, avez-vous vu ma question mise à jour? Prend-il en charge des valeurs répétées?
user238384

@Oscar: java.sun.com/docs/books/jls/third_edition/html/… "L'utilisation de types bruts dans le code écrit après l'introduction de la généricité dans le langage de programmation Java est fortement déconseillée. Il est possible que les futures versions de le langage de programmation Java interdira l'utilisation de types bruts. "
polygenelubricants

2
Réponse de @polygenelubricants mise à jour pour gérer les doublons et les types bruts BTW, la version ..future de Java ... ne se produira jamais. ;)
OscarRyz

37

Vous pouvez essayer intersection()et des subtract()méthodes à partir de CollectionUtils.

intersection()method vous donne une collection contenant des éléments communs et la subtract()méthode vous donne tous les éléments peu communs.

Ils devraient également prendre soin d'éléments similaires


6
A noter que cette solution nécessite Apache Ccommons
Sir Codesalot

9

S'agit-il vraiment de listes (ordonnées, avec doublons), ou sont-elles des ensembles (non ordonnés, pas de doublons)?

Parce que si c'est le dernier, alors vous pouvez utiliser, disons, a java.util.HashSet<E>et le faire dans le temps linéaire prévu en utilisant le pratique retainAll.

    List<String> list1 = Arrays.asList(
        "milan", "milan", "iga", "dingo", "milan"
    );
    List<String> list2 = Arrays.asList(
        "hafil", "milan", "dingo", "meat"
    );

    // intersection as set
    Set<String> intersect = new HashSet<String>(list1);
    intersect.retainAll(list2);
    System.out.println(intersect.size()); // prints "2"
    System.out.println(intersect); // prints "[milan, dingo]"

    // intersection/union as list
    List<String> intersectList = new ArrayList<String>();
    intersectList.addAll(list1);
    intersectList.addAll(list2);
    intersectList.retainAll(intersect);
    System.out.println(intersectList);
    // prints "[milan, milan, dingo, milan, milan, dingo]"

    // original lists are structurally unmodified
    System.out.println(list1); // prints "[milan, milan, iga, dingo, milan]"
    System.out.println(list2); // prints "[hafil, milan, dingo, meat]"

Eh bien, je ne sais vraiment pas quelle structure de données il devrait être. Il a des doublons. Vous pouvez maintenant voir la question mise à jour
user238384

Va-t-il supprimer les valeurs répétées de l'ensemble de données? coz je ne veux perdre aucune valeur :(
user238384

@agazerboy: J'ai essayé de répondre aux deux questions. N'hésitez pas à demander plus de précisions.
polygenelubricants

merci poly. J'ai essayé votre programme avec des doublons par exemple dans la première liste, j'ai ajouté "iga" deux fois mais il m'en a quand même retourné 3 comme réponse. Alors qu'il devrait être 4 maintenant. coz list 1 a 4 valeurs similaires. Si j'ai ajouté une entrée plusieurs fois, cela devrait fonctionner. Que dis-tu? Une autre structure de données?
user238384

6

Utilisation de java 8 removeIf

public int getSimilarItems(){
    List<String> one = Arrays.asList("milan", "dingo", "elpha", "hafil", "meat", "iga", "neeta.peeta");
    List<String> two = new ArrayList<>(Arrays.asList("hafil", "iga", "binga", "mike", "dingo")); //Cannot remove directly from array backed collection
    int initial = two.size();

    two.removeIf(one::contains);
    return initial - two.size();
}

Cela a l'air bien, mais si je veux garder les listes non modifiées, je devrais cloner l'une des listes et cela ne serait pas souhaité dans certains cas.
Sebastian D'Agostino

6

Si vous recherchez un moyen pratique de tester l'égalité de deux collections, vous pouvez utiliser org.apache.commons.collections.CollectionUtils.isEqualCollection, qui compare deux collections indépendamment de l'ordre.


4

De toutes les approches, je trouve que l'utilisation org.apache.commons.collections.CollectionUtils#isEqualCollectionest la meilleure. Voici les raisons -

  • Je n'ai pas à déclarer de liste supplémentaire / définir moi-même
  • Je ne mute pas les listes d'entrée
  • C'est très efficace. Il vérifie l'égalité en complexité O (N).

S'il n'est pas possible d'avoir apache.commons.collectionsune dépendance, je recommanderais d'implémenter l'algorithme qu'il suit pour vérifier l'égalité de la liste en raison de son efficacité.


3

Solution simple: -

    List<String> list = new ArrayList<String>(Arrays.asList("a", "b", "d", "c"));
    List<String> list2 = new ArrayList<String>(Arrays.asList("b", "f", "c"));

    list.retainAll(list2);
    list2.removeAll(list);
    System.out.println("similiar " + list);
    System.out.println("different " + list2);

Production :-

similiar [b, c]
different [f]

1

En supposant hash1ethash2

List< String > sames = whatever
List< String > diffs = whatever

int count = 0;
for( String key : hash1.keySet() )
{
   if( hash2.containsKey( key ) ) 
   {
      sames.add( key );
   }
   else
   {
      diffs.add( key );
   }
}

//sames.size() contains the number of similar elements.

Il veut la liste des clés identiques, pas le nombre de clés identiques. Je pense.
Rosdi Kasim

Merci Stefan pour votre aide. Ouais Rosdi a raison et vous aussi. J'ai également besoin du nombre total de valeurs similaires et de valeurs similaires.
user238384

1

J'ai trouvé un exemple très basique de comparaison de listes à List Compare Cet exemple vérifie d'abord la taille, puis vérifie la disponibilité de l'élément particulier d'une liste dans une autre.


-1
public static boolean compareList(List ls1, List ls2){
    return ls1.containsAll(ls2) && ls1.size() == ls2.size() ? true :false;
     }

public static void main(String[] args) {

    ArrayList<String> one = new ArrayList<String>();
    one.add("one");
    one.add("two");
    one.add("six");

    ArrayList<String> two = new ArrayList<String>();
    two.add("one");
    two.add("six");
    two.add("two");

    System.out.println("Output1 :: " + compareList(one, two));

    two.add("ten");

    System.out.println("Output2 :: " + compareList(one, two));
  }

1
Cette solution renvoie un résultat erroné lorsque deux contient 3 copies de «un». Cela produirait incorrectement un vrai résultat.
Joseph Fitzgerald

Merci pour cette partie: && ls1.size () == ls2.size ()
Nouar

1
Une raison qui vous semble ? true :falsenécessaire dans votre extrait de code?
Krzysztof Tomaszewski
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.