Inhalte von 2 Arrays mit unterschiedlichen Objekten vergleichen

Hallo,

vielleicht habt Ihr mir meine besser Lösung für folgendes Problem. Ich habe zwei Arrays in denen sich je Array unterschiedliche Objekte befinden:

Collection<Foo> fooArray=new ArrayList<Foo>();
Collection<Bar> barArray=new ArrayList<Bar>();

Nun gilt es zu ermitteln, ob die Objekte in den zwei Arrays anhand bestimmter Attribute identisch sind und falls nicht sind die Unterschiede zu ermitteln. Ich kann also nicht einfach die Größe (Anzahl der Elemente) der Arrays vergleichen. Über getter-Methoden der Klassen Foo und Bar kann ich auf Attribute zugreifen die ich zu vergleichen habe:


for (Foo foo : fooArray) {
    boolean exist = false;
    for (Bar bar : barArray) {
       if (bar.getID().equals(foo.getKey())) {
          exist = true;
          tested.add(bar);
          if (! bar.isequals(foo)) {
              // genauerer Vergleich durchführen...
          }
       }
    }
    if (!exist) {
       // foo ist nicht in bar
    }
}
            
barArray.removeAll(tested);

for (Bar bar : barArray) {
  // bar ist nicht in foo
}

Wie Ihr seht, behelfe ich mir mit einem weiteren Array

 Collection<Bar> tested=new ArrayList<Bar>();

in dem ich die vorhandenen Objekte aufsammle.

Gibt es da einen schöneren und einfacheren Weg…

vielen Dank für Eure Tips!

es gibt keine allgemeine contains-Methode die den equal-Prozess herausnimmt
so wie Sortierung mit Comparator,
da ist deine Doppelschleife eine normale Ersetzung, denke ich,


wenn es dir auf Performance ankommt, der quadratische Durchlauf generell zu teuer ist,
dann kannst Wege gehen wie auch höhere Datenstrukturen als Liste

einen gemeinsamen Datentyp für Key für jedes Element inden, z.B. String, was die Keys + Ids vielleicht schon sind,
dann eine Map, alle Elemente der ersten Liste mit Key mappen,
mit zweiter Liste dann nur noch schauen ob Key vorhanden

so kann man auch vorgehen wenn in beiden Listen dieselben Datentypen sind,
das hat mit unterschiedlichen Klassen nicht mehr viel zu tun,
doppelte Keys würden es etwas schwieriger macjen

O(n log n) wird es, wenn man vorher beide Listen nach dem Vergleichskriterium sortiert. Ist immerhin um einiges besser als quadratische Komplexität.

Hallo,

danke für Deine Antwort![QUOTE=SlaterB]
einen gemeinsamen Datentyp für Key für jedes Element inden, z.B. String, was die Keys + Ids vielleicht schon sind,
dann eine Map, alle Elemente der ersten Liste mit Key mappen,
mit zweiter Liste dann nur noch schauen ob Key vorhanden

doppelte Keys würden es etwas schwieriger macjen[/QUOTE] sorry - das hab ich vergessen zu erwähnen. Doppelte Keys sind in diesem Fall theoretisch möglich - zumindest nicht auszuschließen - deshalb kann ich, soweit ich es kapiere, eine Map wohl nicht sooo einfach verwenden.

Dann müsstest du eine Map Key -> Liste mit zum Key passenden Dingen verwenden.

Aber was mir noch anderes durch den Kopf gegangen ist: Wenn Foo und Bar intern teilweise gleiche Attribute haben, kann es Sinn machen, diese gleichen Attribute in eine gemeinsame Basisklasse auszulagern und dann diese Basisklassenobjekte miteinander zu vergleichen?

Und was spricht dagegen Foo nach dem getKey()-Kriterium und Bar nach dem getId()-Kriterium zu sortieren und dann parallel zu iterieren?

barArray.removeAll(tested);

Hoffentlich hast du die equals-Methode richtig implementiert: wenn die Keys doppelt vorkommen können, dann ist das ganze doch reichlich merkwürdig.

Dein Detailvergleich hängt dann ja subtil von der Reihenfolge in der Liste ab…


        private Comparable getKey() {
            throw new UnsupportedOperationException("Not yet implemented");
        }
    }

    private static class Bar {

        private Comparable getID() {
            throw new UnsupportedOperationException("Not yet implemented");
        }
    }

    public static void main(String[] args) throws IOException {
        List<Foo> fooArray = new ArrayList<Foo>();
        //add foo's
        List<Bar> barArray = new ArrayList<Bar>();
        //add bar's
        Foo[] toArray1 = fooArray.toArray(new Foo[0]);
        Bar[] toArray2 = barArray.toArray(new Bar[0]);
        Arrays.sort(toArray1, new Comparator<Foo>() {
            @Override
            public int compare(Foo o1, Foo o2) {
                return o1.getKey().compareTo(o2.getKey());
            }
        });
        Arrays.sort(toArray2, new Comparator<Bar>() {
            @Override
            public int compare(Bar o1, Bar o2) {
                return o1.getID().compareTo(o2.getID());
            }
        });


        boolean successful = true;
        for (Foo foo : toArray1) {
            int i = Arrays.binarySearch(toArray2, foo.getKey());
            if (i == -1 || !foo.equals(toArray2**)) {
                successful = false;
                break;
            }
        }

        System.out.println("gleich = " + successful);
    }```

Wirklich schön ist das jetzt nicht, aber damit vermeidest du in der Theorie auch die n^2 Laufzeit. In der Praxis wird's aber nicht wirklich schneller sein.

[Siehe auch](http://wiki.byte-welt.net/wiki/%3D%3D,_equals%28%29_und_Identit%C3%A4t_und_Gleichheit).