Schnittmenge zwischen zwei Integer-Arrays

Schnittmenge zwischen zwei Integer-Arrays

1. Überblick

In diesem kurzen Tutorial sehen wir uns an, wiecompute the intersection between two Integer arrays ‘a' und‘b'.

Wir werden uns auch darauf konzentrieren, wie doppelte Einträge behandelt werden.

Für die Implementierung verwenden wirStreams.

2. Mitgliedschaftsprädikat für ein Array

Der Schnittpunkt zweier Mengen ist per Definition eine Menge mit allen Werten von einer, die auch Teil der zweiten Menge sind.

Daher benötigen wir einFunction oder vielmehr einPredicate, um die Mitgliedschaft im zweiten Array zu bestimmen. DaList eine solche Methode sofort bereitstellt, wandeln wir sie inList um:

Predicate isContainedInB = Arrays.asList(b)::contains;

3. Aufbau der Kreuzung

Um das resultierende Array aufzubauen, betrachten wir die Elemente des ersten Satzes nacheinander und prüfen, ob sie auch im zweiten Array enthalten sind. Dann erstellen wir darauf basierend ein neues Array.

DieStream API bietet uns die erforderlichen Methoden. First, we’ll create a Stream, then filter with the membership-Predicate and finally we’ll create a new array:

public static Integer[] intersectionSimple(Integer[] a, Integer[] b){
    return Stream.of(a)
      .filter(Arrays.asList(b)::contains)
      .toArray(Integer[]::new);
}

4. Doppelte Einträge

Da Arrays in Java keineSet-Implementierung sind, besteht das Problem doppelter Einträge in der Eingabe und dann im Ergebnis. Beachten Sie, dass die Anzahl der Vorkommen im Ergebnis von den Vorkommen im ersten Parameter abhängt.

Bei Mengen dürfen Elemente jedoch nicht mehrfach vorkommen. We can archive this by using the distinct() method:

public static Integer[] intersectionSet(Integer[] a, Integer[] b){
    return Stream.of(a)
      .filter(Arrays.asList(b)::contain)
      .distinct()
      .toArray(Integer[]::new);
}

Die Länge der Schnittmenge hängt also nicht mehr von der Parameterreihenfolge ab.

Der Schnittpunkt eines Arrays mit sich selbst ist jedoch möglicherweise nicht wieder das Array, da doppelte Einträge entfernt werden.

5. Multiset-Kreuzung

Ein allgemeinerer Begriff, der mehrere gleiche Einträge zulässt, sind Multisets. Für sie wird der Schnittpunkt dann durch die minimale Anzahl von Eingabeereignissen definiert. Unsere Mitgliedschaft -Predicate muss also die Punktzahl behalten, wie oft wir dem Ergebnis ein Element hinzufügen.

Hierfür kann die Methoderemove()verwendet werden, die die Mitgliedschaft zurückgibt und die Elemente verbraucht. Nachdem alle gleichen Elemente in‘b' verbraucht sind, werden dem Ergebnis keine gleichen Elemente mehr hinzugefügt:

public static Integer[] intersectionSet(Integer[] a, Integer[] b){
    return Stream.of(a)
      .filter(new LinkedList<>(Arrays.asList(b))::remove)
      .toArray(Integer[]::new);
}

Da derArrays API nur einen unveränderlichenList, zurückgibt, müssen wir einen dedizierten veränderlichen generieren.

6. Fazit

In diesem Artikel haben wir gesehen, wie die Smethodscontains undremove verwendet werden, um eine Schnittmenge für zwei Arrays in Java zu implementieren.

Alle Implementierungen, Codefragmente und Tests finden Sie in unserenGithub repository - dies ist ein Maven-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein, wie es ist.