Einführung in die Eclipse-Sammlungen

Einführung in Eclipse-Sammlungen

1. Überblick

Eclipse Collections ist ein weiteres verbessertes Sammlungsframework für Java.

Einfach ausgedrückt, bietet es optimierte Implementierungen sowie einige zusätzliche Datenstrukturen und Funktionen, die im Kern-Java nicht zu finden sind.

Die Bibliothek bietet sowohl veränderbare als auch unveränderbare Implementierungen aller Datenstrukturen.

2. Maven-Abhängigkeit

Beginnen wir mit dem Hinzufügen der folgenden Maven-Abhängigkeit zu unserenpom.xml:

org.eclipse.collections
    eclipse-collections
    8.2.0

Die neueste Version der Bibliothek finden Sie inMaven Central Repository.

3. Das große Bild

3.1. Grundlegende Sammlungstypen

Grundlegende Auflistungstypen in Eclipse-Auflistungen sind:

  • ListIterable - eine geordnete Sammlung, die die Einfügereihenfolge beibehält und doppelte Elemente zulässt. Unterschnittstellen umfassen:MutableList,FixedSizeList undImmutableList. Die häufigstenListIterable implementation is FastList, which is a subclass of MutableList

  • SetIterable - eine Sammlung, die keine doppelten Elemente zulässt. Es kann sortiert oder unsortiert sein. Zu den Subschnittstellen gehören:SortedSetIterable undUnsortedSetIterable. Die häufigste unsortierte Implementierung vonSetIterableistUnifiedSet

  • MapIterable - eine Sammlung von Schlüssel / Wert-Paaren. Subschnittstellen umfassenMutableMap,FixedSizeMap undImmutableMap. Zwei gängige Implementierungen sindUnifiedMap undMutableSortedMap. WährendUnifiedMap keine Reihenfolge beibehält, behältMutableSortedMap die natürliche Reihenfolge der Elemente bei

  • BiMap - Eine Sammlung von Schlüssel / Wert-Paaren, die in beide Richtungen durchlaufen werden können. BiMap erweitert die Schnittstelle vonMapIterable

  • Bag - eine ungeordnete Sammlung, die Duplikate zulässt. Subschnittstellen umfassenMutableBag andFixedSizeBag. Die häufigste Implementierung istHashBag

  • StackIterable - Eine Sammlung, die die Reihenfolge "Last-In, First-Out" beibehält und die Elemente in umgekehrter Einfügereihenfolge durchläuft. Subschnittstellen umfassenMutableStack undImmutableStack

  • MultiMap - Eine Sammlung von Schlüssel / Wert-Paaren, die mehrere Werte für jeden Schlüssel zulässt

3.2. Primitive Sammlungen

The framework also provides a huge set of primitive collections; Ihre Implementierungen sind nach dem Typ benannt, den sie enthalten. Für jeden Typ gibt es veränderbare, unveränderbare, synchronisierte und nicht veränderbare Formen:

  • PrimitiveLists

  • PrimitiveSets

  • PrimitiveStacks

  • PrimitiveBags

  • PrimitiveMaps

  • IntInterval

Es gibt eine Vielzahl von primitiven Kartenformen, die alle möglichen Kombinationen von primitiven oder Objektschlüsseln und primitiven oder Objektwerten abdecken.

Eine kurze Anmerkung - einIntInterval ist ein Bereich von Ganzzahlen, über die mit einem Schrittwert iteriert werden kann.

4. Eine Sammlung instanziieren

Um einemArrayList oderHashSet Elemente hinzuzufügen, instanziieren wir eine Sammlung, indem wir den Konstruktor no-arg aufrufen und dann jedes Element einzeln hinzufügen.

Während wir das in Eclipse-Sammlungen noch tun können,we can also instantiate a collection and provide all initial elements at the same time in a single line.

Mal sehen, wie wir einFastList instanziieren können:

MutableList list = FastList.newListWith(
  "Porsche", "Volkswagen", "Toyota", "Mercedes", "Toyota");

In ähnlicher Weise können wir einUnifiedSet instanziieren und Elemente hinzufügen, indem wir die Elemente an die statische Methode vonnewSetWith()übergeben:

Set comparison = UnifiedSet.newSetWith(
  "Porsche", "Volkswagen", "Toyota", "Mercedes");

So können wir einHashBag instanziieren:

MutableBag bag = HashBag.newBagWith(
  "Porsche", "Volkswagen", "Toyota", "Porsche", "Mercedes");

Das Instanziieren von Maps und das Hinzufügen von Schlüssel- und Wertepaaren ist ähnlich. Der einzige Unterschied besteht darin, dass wir die Schlüssel- und Wertepaare als Implementierungen derPair-Schnittstelle an die MethodenewMapWith()übergeben.

Nehmen wir als BeispielUnifiedMap:

Pair pair1 = Tuples.pair(1, "One");
Pair pair2 = Tuples.pair(2, "Two");
Pair pair3 = Tuples.pair(3, "Three");

UnifiedMap map = new UnifiedMap<>(pair1, pair2, pair3);

Wir können weiterhin den Java Collections API-Ansatz verwenden:

UnifiedMap map = new UnifiedMap<>();

map.put(1, "one");
map.put(2, "two");
map.put(3, "three");

Daimmutable collections cannot be modified, they do not have implementations of methods that modify collections wieadd() undremove().

Nicht modifizierbare Sammlungen ermöglichen es uns jedoch, diese Methoden aufzurufen, werfen jedoch einUnsupportedOperationException, wenn wir dies tun.

5. Elemente aus Sammlungen abrufen

Genau wie bei der Verwendung von StandardLists können Elemente von Eclipse CollectionsLists anhand ihres Index abgerufen werden:

list.get(0);

Und Werte von Eclipse Collections-Maps können mithilfe ihres Schlüssels abgerufen werden:

map.get(0);

Die MethodengetFirst() undgetLast() können verwendet werden, um das erste bzw. das letzte Element einer Liste abzurufen. Bei anderen Auflistungen geben sie das erste und das letzte Element zurück, die von einem Iterator zurückgegeben würden.

map.getFirst();
map.getLast();

Mit den Methodenmax() undmin() können die Maximal- und Minimalwerte einer Sammlung basierend auf der natürlichen Reihenfolge ermittelt werden.

map.max();
map.min();

6. Durch eine Sammlung iterieren

Eclipse-Sammlungen bieten viele Möglichkeiten zum Durchlaufen von Sammlungen. Mal sehen, was sie sind und wie sie in der Praxis funktionieren.

6.1. Sammlungsfilterung

Das Auswahlmuster gibt eine neue Sammlung zurück, die Elemente einer Sammlung enthält, die eine logische Bedingung erfüllen. Es ist im Wesentlichen eine Filteroperation.

Hier ist ein Beispiel:

@Test
public void givenListwhenSelect_thenCorrect() {
    MutableList greaterThanThirty = list
      .select(Predicates.greaterThan(30))
      .sortThis();

    Assertions.assertThat(greaterThanThirty)
      .containsExactly(31, 38, 41);
}

Dasselbe kann mit einem einfachen Lambda-Ausdruck erreicht werden:

return list.select(i -> i > 30)
  .sortThis();

Das Rückweisungsmuster ist das Gegenteil. Es wird eine Auflistung aller Elemente zurückgegeben, die eine logische Bedingung nicht erfüllen.

Sehen wir uns ein Beispiel an:

@Test
public void whenReject_thenCorrect() {
    MutableList notGreaterThanThirty = list
      .reject(Predicates.greaterThan(30))
      .sortThis();

    Assertions.assertThat(notGreaterThanThirty)
      .containsExactlyElementsOf(this.expectedList);
}

Hier lehnen wir alle Elemente ab, die größer als 30 sind.

6.2. Diecollect()-Methode

Die Methodecollect gibt eine neue Sammlung zurück, deren Elemente die Ergebnisse sind, die vom bereitgestellten Lambda-Ausdruck zurückgegeben werden. Im Wesentlichen handelt es sich um eine Kombination dermap() undcollect() aus der Stream-API.

Lassen Sie es uns in Aktion sehen:

@Test
public void whenCollect_thenCorrect() {
    Student student1 = new Student("John", "Hopkins");
    Student student2 = new Student("George", "Adams");

    MutableList students = FastList
      .newListWith(student1, student2);

    MutableList lastNames = students
      .collect(Student::getLastName);

    Assertions.assertThat(lastNames)
      .containsExactly("Hopkins", "Adams");
}

Die erstellte SammlunglastNames enthält die Nachnamen, die aus der Listestudents erfasst wurden.

Aberwhat if the returned collection is a collection of collections and we do not want to maintain a nested structure?

Wenn beispielsweise jeder Schüler mehrere Adressen hat und wir eine Sammlung benötigen, die die Adressen alsStrings anstelle einer Sammlung von Sammlungen enthält, können wir die MethodeflatCollect() verwenden.

Hier ist ein Beispiel:

@Test
public void whenFlatCollect_thenCorrect() {
    MutableList addresses = students
      .flatCollect(Student::getAddresses);

    Assertions.assertThat(addresses)
      .containsExactlyElementsOf(this.expectedAddresses);
}

6.3. Elementerkennung

Die Methodedetect findet und gibt das erste Element zurück, das eine logische Bedingung erfüllt.

Lassen Sie uns ein kurzes Beispiel durchgehen:

@Test
public void whenDetect_thenCorrect() {
    Integer result = list.detect(Predicates.greaterThan(30));

    Assertions.assertThat(result)
      .isEqualTo(41);
}

Die MethodeanySatisfybestimmt, ob ein Element einer Sammlung eine logische Bedingung erfüllt.

Hier ist ein Beispiel:

@Test
public void whenAnySatisfiesCondition_thenCorrect() {
    boolean result = list.anySatisfy(Predicates.greaterThan(30));

    assertTrue(result);
}

In ähnlicher Weise bestimmt die MethodeallSatisfy, ob alle Elemente einer Sammlung eine logische Bedingung erfüllen.

Sehen wir uns ein kurzes Beispiel an:

@Test
public void whenAnySatisfiesCondition_thenCorrect() {
    boolean result = list.allSatisfy(Predicates.greaterThan(0));

    assertTrue(result);
}

6.4. Diepartition()-Methode

Die Methodepartition ordnet jedes Element einer Sammlung einer von zwei Sammlungen zu, je nachdem, ob das Element eine logische Bedingung erfüllt oder nicht.

Sehen wir uns ein Beispiel an:

@Test
public void whenAnySatisfiesCondition_thenCorrect() {
    MutableList numbers = list;
    PartitionMutableList partitionedFolks = numbers
      .partition(i -> i > 30);

    MutableList greaterThanThirty = partitionedFolks
      .getSelected()
      .sortThis();
    MutableList smallerThanThirty = partitionedFolks
      .getRejected()
      .sortThis();

    Assertions.assertThat(smallerThanThirty)
      .containsExactly(1, 5, 8, 17, 23);
    Assertions.assertThat(greaterThanThirty)
      .containsExactly(31, 38, 41);
}

6.5. Lazy Iteration

Lazy Iteration ist ein Optimierungsmuster, in dem eine Iterationsmethode aufgerufen wird, aber ihre tatsächliche Ausführung wird verzögert, bis ihre Aktion oder Rückgabewerte von einer anderen nachfolgenden Methode benötigt werden.

@Test
public void whenLazyIteration_thenCorrect() {
    Student student1 = new Student("John", "Hopkins");
    Student student2 = new Student("George", "Adams");
    Student student3 = new Student("Jennifer", "Rodriguez");

    MutableList students = Lists.mutable
      .with(student1, student2, student3);
    LazyIterable lazyStudents = students.asLazy();
    LazyIterable lastNames = lazyStudents
      .collect(Student::getLastName);

    Assertions.assertThat(lastNames)
      .containsAll(Lists.mutable.with("Hopkins", "Adams", "Rodriguez"));
}

Hier ruft daslazyStudents-Objekt die Elemente derstudents-Liste erst ab, wenn diecollect()-Methode aufgerufen wird.

7. Sammlungselemente koppeln

Die Methodezip() gibt eine neue Sammlung zurück, indem Elemente zweier Sammlungen zu Paaren kombiniert werden. Wenn eine der beiden Sammlungen länger ist, werden die verbleibenden Elemente abgeschnitten.

Mal sehen, wie wir es nutzen können:

@Test
public void whenZip_thenCorrect() {
    MutableList numbers = Lists.mutable
      .with("1", "2", "3", "Ignored");
    MutableList cars = Lists.mutable
      .with("Porsche", "Volvo", "Toyota");
    MutableList> pairs = numbers.zip(cars);

    Assertions.assertThat(pairs)
      .containsExactlyElementsOf(this.expectedPairs);
}

Wir können die Elemente einer Sammlung auch mit ihren Indizes mithilfe derzipWithIndex()-Methode koppeln:

@Test
public void whenZip_thenCorrect() {
    MutableList cars = FastList
      .newListWith("Porsche", "Volvo", "Toyota");
    MutableList> pairs = cars.zipWithIndex();

    Assertions.assertThat(pairs)
      .containsExactlyElementsOf(this.expectedPairs);
}

8. Sammlungen konvertieren

Eclipse Collections bietet einfache Methoden zum Konvertieren eines Containertyps in einen anderen. Diese Methoden sindtoList(),toSet(),toBag() undtoMap().

Mal sehen, wie wir sie nutzen können:

public static List convertToList() {
    UnifiedSet cars = new UnifiedSet<>();

    cars.add("Toyota");
    cars.add("Mercedes");
    cars.add("Volkswagen");

    return cars.toList();
}

Lassen Sie uns unseren Test durchführen:

@Test
public void whenConvertContainerToAnother_thenCorrect() {
    MutableList cars = (MutableList) ConvertContainerToAnother
      .convertToList();

    Assertions.assertThat(cars)
      .containsExactlyElementsOf(
      FastList.newListWith("Volkswagen", "Toyota", "Mercedes"));
}

9. Fazit

In diesem Tutorial haben wir einen schnellen Überblick über Eclipse-Sammlungen und die von ihnen bereitgestellten Funktionen erhalten.

Die vollständige Implementierung dieses Tutorials ist inover on GitHub verfügbar.