Apache Commons Collections Bag

Apache Commons-Sammlungs-Tasche

1. Einführung

In diesem kurzen Artikel konzentrieren wir uns auf die Verwendung derBag-Sammlung von Apache.

Weitere Lektüre:

Apache Commons BeanUtils

Erfahren Sie, wie Sie Apache Commons BeanUtils für allgemeine Bean-Operationen verwenden.

Read more

Apache Commons IO

Eine schnelle und praktische Anleitung zur Apache Commons IO-Open-Source-Bibliothek für Java, in der viele der bekannteren Funktionen behandelt werden.

Read more

Einführung in Apache Commons Text

Erfahren Sie, wie Sie Apache Commons Text für allgemeine Zeichenfolgenoperationen verwenden.

Read more

2. Maven-Abhängigkeit

Bevor wir beginnen, müssen wir die neuesten Abhängigkeiten ausMaven Central importieren:


    org.apache.commons
    commons-collections4
    4.1

3. Taschen gegen Sammlungen

Einfach ausgedrückt istBag eine Sammlung, mit der mehrere Elemente zusammen mit ihrer Wiederholungszahl gespeichert werden können:

public void whenAdded_thenCountIsKept() {
    Bag bag = new HashBag<>(
      Arrays.asList(1, 2, 3, 3, 3, 1, 4));

    assertThat(2, equalTo(bag.getCount(1)));
}

3.1. Verstöße gegen den Vertrag vonCollection

Beim Lesen der API-Dokumentation vonBagtellen wir möglicherweise fest, dass einige Methoden als Verstoß gegen den Standard-Java-Sammlungsvertrag gekennzeichnet sind.

Wenn wir beispielsweise eineadd()-API aus einer Java-Sammlung verwenden, erhalten wirtrue, auch wenn sich das Element bereits in der Sammlung befindet:

Collection collection = new ArrayList<>();
collection.add(1);
assertThat(collection.add(1), is(true));

Dieselbe API aus der Implementierung vonBaggibtfalsezurück, wenn wir ein Element hinzufügen, das bereits in der Auflistung verfügbar ist:

Bag bag = new HashBag<>();
bag.add(1);

assertThat(bag.add(1), is(not(true)));

Um diese Probleme zu beheben, bietet die Bibliothek von Apache Collections einen Dekorator namensCollectionBag.. Wir können diesen verwenden, um unsere Taschensammlungen mit dem Vertrag von JavaCollectionkompatibel zu machen:

public void whenBagAddAPILikeCollectionAPI_thenTrue() {
    Bag bag = CollectionBag.collectionBag(new HashBag<>());
    bag.add(1);

    assertThat(bag.add(1), is((true)));
}

4. Taschenimplementierungen

Lassen Sie uns nun die verschiedenen Implementierungen derBag-Schnittstelle untersuchen - innerhalb der Apache-Sammlungsbibliothek.

4.1. HashBag

Wir können ein Element hinzufügen und die API anweisen, wie viele Exemplare dieses Elements in unserer Beutelsammlung enthalten soll:

public void givenAdd_whenCountOfElementsDefined_thenCountAreAdded() {
    Bag bag = new HashBag<>();

    bag.add(1, 5); // adding 1 five times

    assertThat(5, equalTo(bag.getCount(1)));
}

Wir können auch eine bestimmte Anzahl von Kopien oder jede Instanz eines Elements aus unserer Tasche löschen:

public void givenMultipleCopies_whenRemove_allAreRemoved() {
    Bag bag = new HashBag<>(
      Arrays.asList(1, 2, 3, 3, 3, 1, 4));

    bag.remove(3, 1); // remove one element, two still remain
    assertThat(2, equalTo(bag.getCount(3)));

    bag.remove(1); // remove all
    assertThat(0, equalTo(bag.getCount(1)));
}

4.2. TreeBag

Die Implementierung vonTreeBagfunktioniert wie jeder andere Baum und behält zusätzlich die Semantik vonBagbei.

Wir können natürlich ein Array von Ganzzahlen mit einemTreeBag sortieren und dann die Anzahl der Instanzen abfragen, die jedes einzelne Element in der Sammlung hat:

public void givenTree_whenDuplicateElementsAdded_thenSort() {
    TreeBag bag = new TreeBag<>(Arrays.asList(7, 5,
      1, 7, 2, 3, 3, 3, 1, 4, 7));

    assertThat(bag.first(), equalTo(1));
    assertThat(bag.getCount(bag.first()), equalTo(2));
    assertThat(bag.last(), equalTo(7));
    assertThat(bag.getCount(bag.last()), equalTo(3));
}

DasTreeBag implementiert eineSortedBag-Schnittstelle. Alle Implementierungen dieser Schnittstelle können den DecoratorCollectionSortedBag verwenden, um den Java Collections-Vertrag einzuhalten:

public void whenTreeAddAPILikeCollectionAPI_thenTrue() {
    SortedBag bag
      = CollectionSortedBag.collectionSortedBag(new TreeBag<>());

    bag.add(1);

    assertThat(bag.add(1), is((true)));
}

4.3. SynchronizedSortedBag

Eine weitere weit verbreitete Implementierung vonBag istSynchronizedSortedBag. Genau genommen ist dies ein synchronisierter Dekorator der Implementierung vonSortedBag.

Wir können diesen Dekorator mit unserenTreeBag (eine Implementierung vonSortedBag) aus dem vorherigen Abschnitt verwenden, um den Zugriff auf unsere Tasche zu synchronisieren:

public void givenSortedBag_whenDuplicateElementsAdded_thenSort() {
    SynchronizedSortedBag bag = SynchronizedSortedBag
      .synchronizedSortedBag(new TreeBag<>(
        Arrays.asList(7, 5, 1, 7, 2, 3, 3, 3, 1, 4, 7)));

    assertThat(bag.first(), equalTo(1));
    assertThat(bag.getCount(bag.first()), equalTo(2));
    assertThat(bag.last(), equalTo(7));
    assertThat(bag.getCount(bag.last()), equalTo(3));
}

Wir können eine Kombination von APIs verwenden -Collections.synchronizedSortedMap() undTreeMap –, um zu simulieren, was wir hier mitSynchronizedSortedBag gemacht haben.

5. Fazit

In diesem kurzen Tutorial haben wir dieBag-Schnittstelle und ihre verschiedenen Implementierungen kennengelernt.

Wie immer finden Sie den Code für diesen Artikel inover on GitHub.