API-Handbuch für Vavr-Sammlungen

VAVR (früher bekannt als Javaslang) ist eine gemeinnützige Funktionsbibliothek für Java 8+. Es ermöglicht Ihnen das Schreiben von funktionalem Scala-ähnlichem Code in Java und dient dazu, die Codemenge zu reduzieren und die Qualität zu verbessern. Bibliotheksseite .

Unter dem Schnitt befindet sich eine Übersetzung eines Artikels, der Informationen zur Vavr Collections-API systematisiert.

Übersetzt von @middle_java

Letzter geänderter Originalartikel: 15. August 2019

1. Übersicht


Die Vavr-Bibliothek, früher als Javaslang bekannt, ist eine funktionale Bibliothek für Java. In diesem Artikel untersuchen wir die leistungsstarke Sammlungs-API.

Weitere Informationen zu dieser Bibliothek finden Sie in diesem Artikel .

2. Persistente Sammlungen


Wenn eine persistente Sammlung geändert wird, wird eine neue Version der Sammlung erstellt, ohne die aktuelle Version zu ändern.

Die Unterstützung mehrerer Versionen derselben Sammlung kann zu einer ineffizienten Nutzung von CPU und Speicher führen. Die Vavr-Sammlungsbibliothek überwindet dies jedoch, indem sie die Datenstruktur zwischen verschiedenen Versionen der Sammlung teilt.

Dies unterscheidet sich grundlegend von unmodifiableCollection() von der Java-Dienstprogrammklasse Collections , die lediglich einen Wrapper für die Basissammlung bereitstellt.

Beim Versuch, eine solche Sammlung zu ändern, wird UnsupportedOperationException anstatt eine neue Version zu erstellen. Darüber hinaus ist die Basissammlung durch eine direkte Verknüpfung weiterhin veränderbar.

3. Durchfahrbar


Traversable ist der Basistyp aller Vavr-Sammlungen. Diese Schnittstelle definiert Methoden, die allen Datenstrukturen gemeinsam sind.

Es bietet einige nützliche Standardmethoden wie size() , get() , filter() , isEmpty() und andere, die von isEmpty() geerbt werden.

Wir erkunden die Sammlungsbibliothek weiter.

4. Seq


Beginnen wir mit den Sequenzen.

Die Seq Schnittstelle ist eine sequentielle Datenstruktur. Dies ist die übergeordnete Schnittstelle für List , Stream , Queue , Array , Vector und CharSeq . Alle diese Datenstrukturen haben ihre eigenen einzigartigen Eigenschaften, die wir unten diskutieren werden.

4.1. Liste


List ist eine energetisch berechnete (eifrig evaluierte Operation, sobald die Werte ihrer Operanden bekannt werden), eine Folge von Elementen, die die LinearSeq Schnittstelle erweitern.

Persistente List rekursiv mit Kopf und Schwanz erstellt :

  • Der Kopf ist das erste Element
  • Schwanz - eine Liste mit den verbleibenden Elementen (diese Liste besteht auch aus Kopf und Schwanz)

Die List API enthält statische Factory-Methoden, mit denen Sie eine List erstellen können. Mit of() Methode static of() können Sie eine Instanz von List aus einem oder mehreren Objekten erstellen.

Sie können auch die statische Methode empty() verwenden, um eine leere List zu erstellen, und die Methode ofAll() , um eine List vom Typ Iterable zu erstellen:

 List < String > list = List.of( "Java", "PHP", "Jquery", "JavaScript", "JShell", "JAVA"); 

Schauen wir uns einige Beispiele für Listenmanipulationen an.

Wir können die drop() -Methode und ihre Varianten verwenden, um die ersten N Elemente zu entfernen:

 List list1 = list.drop(2); assertFalse(list1.contains("Java") && list1.contains("PHP")); List list2 = list.dropRight(2); assertFalse(list2.contains("JAVA") && list2.contains("JShell")); List list3 = list.dropUntil(s - > s.contains("Shell")); assertEquals(list3.size(), 2); List list4 = list.dropWhile(s - > s.length() > 0); assertTrue(list4.isEmpty()); 

drop(int n) entfernt n Elemente aus der Liste, beginnend mit dem ersten Element, während dropRight() dasselbe tut, beginnend mit dem letzten Element in der Liste.

dropUntil() entfernt die Elemente aus der Liste, bis das Prädikat true , während dropWhile() die Elemente entfernt, bis das Prädikat true .

Es gibt auch die dropRightWhile() und dropRightUntil() , mit denen Elemente von rechts entfernt entfernt werden.

Als nächstes wird take(int n) verwendet, um Elemente aus der Liste abzurufen. Es nimmt n Elemente aus der Liste und stoppt dann. Es gibt auch takeRight(int n) , das Elemente vom Ende der Liste übernimmt:

 List list5 = list.take(1); assertEquals(list5.single(), "Java"); List list6 = list.takeRight(1); assertEquals(list5.single(), "Java"); List list7 = list.takeUntil(s - > s.length() > 6); assertEquals(list3.size(), 3); 

Schließlich nimmt takeUntil() Elemente aus der Liste, bis das Prädikat true . Es gibt eine Variante von takeWhile() , die auch ein Prädikatargument takeWhile() .

Darüber hinaus verfügt die API über andere nützliche Methoden, z. B. sogar distinct() , das eine Liste von Elementen mit gelöschten Duplikaten zurückgibt, sowie distinctBy() , das Comparator akzeptiert, um die Gleichheit zu bestimmen.

Es ist sehr interessant, dass es auch intersperse() , das ein Element zwischen jedes Element der Liste einfügt. Dies kann für Operationen mit String sehr praktisch sein:

 List list8 = list .distinctBy((s1, s2) - > s1.startsWith(s2.charAt(0) + "") ? 0 : 1); assertEquals(list3.size(), 2); String words = List.of("Boys", "Girls") .intersperse("and") .reduce((s1, s2) - > s1.concat(" " + s2)) .trim(); assertEquals(words, "Boys and Girls"); 

Möchten Sie die Liste in Kategorien aufteilen? Und dafür gibt es eine API:

 Iterator < List < String >> iterator = list.grouped(2); assertEquals(iterator.head().size(), 2); Map < Boolean, List < String >> map = list.groupBy(e - > e.startsWith("J")); assertEquals(map.size(), 2); assertEquals(map.get(false).get().size(), 1); assertEquals(map.get(true).get().size(), 5); 

Die group(int n) -Methode teilt List in Gruppen von jeweils n Elementen auf. Die groupdBy() -Methode verwendet eine Function , die die Logik zum Aufteilen der Liste enthält, und gibt eine Map mit zwei Elementen zurück: true und false .

Der true Schlüssel wird der List Elemente zugeordnet, die die in Function angegebene Bedingung erfüllen. Der false Schlüssel wird der List Elemente zugeordnet, die diese Bedingung nicht erfüllen.

Wie erwartet ändert sich beim Ändern der List die ursprüngliche List nicht. Stattdessen List immer die neue Version von List zurückgegeben.

Wir können auch mit List interagieren, indem wir die Semantik des Stapels verwenden und Elemente nach dem LIFO-Prinzip (Last In, First Out) extrahieren. In diesem Sinne gibt es API-Methoden wie peek() , pop() und push() , um den Stapel zu manipulieren:

 List < Integer > intList = List.empty(); List < Integer > intList1 = intList.pushAll(List.rangeClosed(5, 10)); assertEquals(intList1.peek(), Integer.valueOf(10)); List intList2 = intList1.pop(); assertEquals(intList2.size(), (intList1.size() - 1)); 

Mit der Funktion pushAll() wird ein Bereich von Ganzzahlen in den Stapel pushAll() , und mit der Funktion pushAll() wird das pushAll() des Stapels abgerufen. Es gibt auch eine peekOption() -Methode, mit der das Ergebnis in ein Option Objekt eingeschlossen werden kann.

Es gibt andere interessante und wirklich nützliche Methoden in der List Oberfläche, die in Java-Dokumenten gründlich dokumentiert sind.

4.2. Warteschlange


In der unveränderlichen Queue werden Elemente Queue , sodass Sie sie nach dem FIFO-Prinzip abrufen können (first in, first out).

Queue besteht aus zwei verknüpften Listen: der vorderen und der hinteren List . Die vordere List enthält Elemente, die aus der Warteschlange entfernt wurden, und die hintere List enthält die Elemente in der Warteschlange.

Auf diese Weise können Sie die Operationen zum Einreihen und Entfernen aus der Warteschlange auf die Komplexität O (1) setzen . Wenn die List in der vorderen List endet, wenn sie aus der Warteschlange entfernt wird, wird die hintere List umgekehrt und zur neuen vorderen List .

Erstellen wir eine Warteschlange:

 Queue < Integer > queue = Queue.of(1, 2); Queue < Integer > secondQueue = queue.enqueueAll(List.of(4, 5)); assertEquals(3, queue.size()); assertEquals(5, secondQueue.size()); Tuple2 < Integer, Queue < Integer >> result = secondQueue.dequeue(); assertEquals(Integer.valueOf(1), result._1); Queue < Integer > tailQueue = result._2; assertFalse(tailQueue.contains(secondQueue.get(0))); 

Die Funktion dequeue() entfernt das head-Element aus der Queue und gibt Tuple2<T, Q> . Das erste Element des Tupels ist das aus der Warteschlange entfernte Kopfelement, das zweite Element des Tupels sind die verbleibenden Queue .

Wir können die combination(n) , um alle möglichen N Kombinationen von Elementen in der Queue :

 Queue < Queue < Integer >> queue1 = queue.combinations(2); assertEquals(queue1.get(2).toCharSeq(), CharSeq.of("23")); 

Auch hier ändert sich die ursprüngliche Queue beim Hinzufügen / Entfernen von Elementen zur Warteschlange nicht.

4.3. Stream


Stream ist eine Implementierung einer träge verknüpften Liste, die sich erheblich von java.util.stream . Im Gegensatz zu java.util.stream speichert Stream Vavr Daten und berechnet nachfolgende Elemente träge.
Angenommen, wir haben Stream Ganzzahlen:

 Stream < Integer > s = Stream.of(2, 1, 3, 4); 

Beim Drucken des Ergebnisses von s.toString() in der Konsole wird nur Stream (2,?) Angezeigt. Dies bedeutet, dass nur das Stream Kopfelement berechnet wurde, die Endelemente jedoch nicht.

s.get(3) Sie s.get(3) und dann das Ergebnis von s.tail() anzeigen, wird Stream (1, 3, 4 s.tail() . Im Gegenteil, wenn Sie nicht zuerst s.get(3) aufrufen, s.get(3) Stream das letzte Element berechnet, ist nur Stream (1 s.tail() ) Das Ergebnis von s.tail() ) . Dies bedeutet, dass nur das erste Endelement berechnet wurde.

Dieses Verhalten kann die Leistung verbessern und ermöglicht die Verwendung von Stream zur Darstellung von Sequenzen, die (theoretisch) unendlich lang sind.
Stream in Vavr ist unveränderlich und kann Empty oder Cons . Cons bestehen aus dem Kopfelement und dem träge berechneten Schwanz des Stream . Im Gegensatz zu List speichert Stream das head-Element im Speicher. Schwanzelemente werden nach Bedarf berechnet.

Erstellen wir einen Stream mit 10 positiven Ganzzahlen und berechnen die Summe der geraden Zahlen:

 Stream < Integer > intStream = Stream.iterate(0, i - > i + 1) .take(10); assertEquals(10, intStream.size()); long evenSum = intStream.filter(i - > i % 2 == 0) .sum() .longValue(); assertEquals(20, evenSum); 

Im Gegensatz zur Stream API von Java 8 ist Stream in Vavr eine Datenstruktur zum Speichern einer Folge von Elementen.

Daher verfügt es über Methoden wie get() , append() , insert() und andere zum Bearbeiten seiner Elemente. drop() , distinct() und einige andere zuvor diskutierte Methoden sind ebenfalls verfügbar.

Lassen Sie uns abschließend tabulate() in Stream demonstrieren. Diese Methode gibt einen Stream Länge n , der Elemente enthält, die das Ergebnis der Anwendung der Funktion sind:

 Stream < Integer > s1 = Stream.tabulate(5, (i) - > i + 1); assertEquals(s1.get(2).intValue(), 3); 

Wir können auch zip() , um einen Stream aus Tuple2<Integer, Integer> zu erstellen, der Elemente enthält, die durch Kombinieren von zwei Stream :

 Stream < Integer > s = Stream.of(2, 1, 3, 4); Stream < Tuple2 < Integer, Integer >> s2 = s.zip(List.of(7, 8, 9)); Tuple2 < Integer, Integer > t1 = s2.get(0); assertEquals(t1._1().intValue(), 2); assertEquals(t1._2().intValue(), 7); 

4.4. Array


Array ist eine unveränderliche indizierte Sequenz, die einen effizienten Direktzugriff ermöglicht. Es basiert auf einem Java- Array von Objekten. Im Wesentlichen ist dies ein Traversable Wrapper für ein Array von Objekten vom Typ T

Sie können eine Instanz von Array mit der statischen Methode of() erstellen. Darüber hinaus können Sie mit den statischen Methoden range() und rangeBy() eine Reihe von Elementen erstellen. Die rangeBy() -Methode verfügt über einen dritten Parameter, mit dem Sie den Schritt bestimmen können.

Die Methoden range() und rangeBy() erstellen Elemente, beginnend nur vom Anfangswert bis zum Endwert minus eins. Wenn wir den Endwert rangeClosed() , können wir rangeClosed() oder rangeClosedBy() :

 Array < Integer > rArray = Array.range(1, 5); assertFalse(rArray.contains(5)); Array < Integer > rArray2 = Array.rangeClosed(1, 5); assertTrue(rArray2.contains(5)); Array < Integer > rArray3 = Array.rangeClosedBy(1, 6, 2); assertEquals(list3.size(), 3); 

Lassen Sie uns mit den Elementen anhand des Index arbeiten:

 Array < Integer > intArray = Array.of(1, 2, 3); Array < Integer > newArray = intArray.removeAt(1); assertEquals(3, intArray.size()); assertEquals(2, newArray.size()); assertEquals(3, newArray.get(1).intValue()); Array < Integer > array2 = intArray.replace(1, 5); assertEquals(s1.get(0).intValue(), 5); 

4.5. Vektor


Vector ist eine Kreuzung zwischen Array und List , die eine weitere indizierte Folge von Elementen bereitstellt und sowohl den wahlfreien Zugriff als auch die Änderung in konstanter Zeit ermöglicht:

 Vector < Integer > intVector = Vector.range(1, 5); Vector < Integer > newVector = intVector.replace(2, 6); assertEquals(4, intVector.size()); assertEquals(4, newVector.size()); assertEquals(2, intVector.get(1).intValue()); assertEquals(6, newVector.get(1).intValue()); 

4.6. Charseq


CharSeq ist ein Sammlungsobjekt zur Darstellung einer Folge primitiver Zeichen. Im Wesentlichen ist dies ein Wrapper für String mit zusätzlichen Erfassungsoperationen.

Um CharSeq zu erstellen, müssen Sie Folgendes tun.

 CharSeq chars = CharSeq.of("vavr"); CharSeq newChars = chars.replace('v', 'V'); assertEquals(4, chars.size()); assertEquals(4, newChars.size()); assertEquals('v', chars.charAt(0)); assertEquals('V', newChars.charAt(0)); assertEquals("Vavr", newChars.mkString()); 

5. Stellen Sie ein


In diesem Abschnitt werden die verschiedenen Implementierungen von Set in der Sammlungsbibliothek erläutert. Ein einzigartiges Merkmal der Set Datenstruktur ist, dass keine doppelten Werte zulässig sind.

Es gibt verschiedene Implementierungen von Set . Das wichtigste ist HashSet . TreeSet erlaubt keine doppelten Elemente und kann sortiert werden. LinkedHashSet die LinkedHashSet der Elemente bei.

Schauen wir uns diese Implementierungen nacheinander genauer an.

5.1. Hashset


HashSet verfügt über statische Factory-Methoden zum Erstellen neuer Instanzen. Einige davon haben wir weiter oben in diesem Artikel untersucht, zum Beispiel of() , ofAll() und Variationen der range() -Methoden.

Die Differenz zwischen den beiden Mengen kann mit der diff() -Methode ermittelt werden. Außerdem geben die Methoden union() und intersect() die Vereinigung und den Schnittpunkt zweier Mengen zurück :

 HashSet < Integer > set0 = HashSet.rangeClosed(1, 5); HashSet < Integer > set0 = HashSet.rangeClosed(1, 5); assertEquals(set0.union(set1), HashSet.rangeClosed(1, 6)); assertEquals(set0.diff(set1), HashSet.rangeClosed(1, 2)); assertEquals(set0.intersect(set1), HashSet.rangeClosed(3, 5)); 

Wir können auch grundlegende Operationen ausführen, z. B. das Hinzufügen und Entfernen von Elementen:

 HashSet < String > set = HashSet.of("Red", "Green", "Blue"); HashSet < String > newSet = set.add("Yellow"); assertEquals(3, set.size()); assertEquals(4, newSet.size()); assertTrue(newSet.contains("Yellow")); 

Die HashSet Implementierung basiert auf dem Hash Array Mapped Trie (HAMT) , das im Vergleich zur üblichen HashTable eine überlegene Leistung HashTable und aufgrund seiner Struktur für die Unterstützung persistenter Sammlungen geeignet ist.

5.2. Baumset


TreeSet ist eine Implementierung der SortedSet Schnittstelle. Es speichert eine Reihe sortierter Elemente und wird mithilfe von binären Suchbäumen implementiert. Alle seine Operationen werden während der O (log n) Zeit ausgeführt .

Standardmäßig werden TreeSet Elemente in ihrer natürlichen Reihenfolge sortiert.
Erstellen wir ein SortedSet mit einer natürlichen Sortierreihenfolge:

 SortedSet < String > set = TreeSet.of("Red", "Green", "Blue"); assertEquals("Blue", set.head()); SortedSet < Integer > intSet = TreeSet.of(1, 2, 3); assertEquals(2, intSet.average().get().intValue()); 

TreeSet beim Erstellen des TreeSet eine Comparator Instanz, um Elemente auf benutzerdefinierte Weise TreeSet . Sie können eine Zeichenfolge auch aus einer Reihe von Elementen erstellen:

 SortedSet < String > reversedSet = TreeSet.of(Comparator.reverseOrder(), "Green", "Red", "Blue"); assertEquals("Red", reversedSet.head()); String str = reversedSet.mkString(" and "); assertEquals("Red and Green and Blue", str); 

5.3. Bitset


Vavr-Sammlungen haben auch eine unveränderliche BitSet Implementierung. Die BitSet Schnittstelle erweitert die SortedSet Schnittstelle. BitSet kann mit statischen Methoden in BitSet.Builder .
Wie bei anderen Implementierungen der Set Datenstruktur können Sie mit BitSet keine doppelten Datensätze zu einem Set hinzufügen.

Es erbt Manipulationsmethoden von der Traversable Schnittstelle. Beachten Sie, dass es sich von java.util.BitSet von der Standard-Java-Bibliothek unterscheidet. BitSet Daten dürfen keine String Werte enthalten.

Erstellen Sie eine Instanz von BitSet mit der Factory-Methode of() :

 BitSet < Integer > bitSet = BitSet.of(1, 2, 3, 4, 5, 6, 7, 8); BitSet < Integer > bitSet1 = bitSet.takeUntil(i - > i > 4); assertEquals(list3.size(), 4); 

Um die ersten vier BitSet Elemente auszuwählen BitSet wir den Befehl takeUntil() . Die Operation hat eine neue Instanz zurückgegeben. Beachten Sie, dass die takeUntil() -Methode in der Traversable Schnittstelle definiert ist, die die übergeordnete Schnittstelle für BitSet .

Andere oben in der Traversable Schnittstelle definierte Methoden und Operationen gelten auch für BitSet .

6. Karte


Map ist eine Schlüsselwertdatenstruktur. Map in Vavr ist unveränderlich und verfügt über Implementierungen für HashMap , TreeMap und LinkedHashMap .

In der Regel lassen Kartenverträge keine doppelten Schlüssel zu, während doppelte Werte, die verschiedenen Schlüsseln zugeordnet sind, möglicherweise doppelt vorhanden sind.

6.1. Hashmap


HashMap ist eine Implementierung der unveränderlichen Map Schnittstelle. Es speichert Schlüssel-Wert-Paare unter Verwendung eines Hash von Schlüsseln.

Map in Vavr verwendet Tuple2 , um Schlüssel-Wert-Paare anstelle des herkömmlichen Eintragstyps Tuple2 :

 Map < Integer, List < Integer >> map = List.rangeClosed(0, 10) .groupBy(i - > i % 2); assertEquals(2, map.size()); assertEquals(6, map.get(0).get().size()); assertEquals(5, map.get(1).get().size()); 

Wie bei HashSet basiert die Implementierung von HashMap auf dem Hash Array Mapped Trie (HAMT) , was zu einer konstanten Zeit für fast alle Operationen führt.
filterKeys() können mit der Methode filterKeys() nach Schlüsseln oder mit der Methode filterKeys() nach Werten filterValues() werden. Beide Methoden verwenden Predicate als Argument:

 Map < String, String > map1 = HashMap.of("key1", "val1", "key2", "val2", "key3", "val3"); Map < String, String > fMap = map1.filterKeys(k - > k.contains("1") || k.contains("2")); assertFalse(fMap.containsKey("key3")); Map < String, String > map1 = map1.filterValues(v - > v.contains("3")); assertEquals(list3.size(), 1); assertTrue(fMap2.containsValue("val3")); 

Sie können Kartenelemente auch mit der map() -Methode transformieren. Konvertieren wir beispielsweise map1 in Map<String, Integer> :

 Map < String, Integer > map2 = map1.map( (k, v) - > Tuple.of(k, Integer.valueOf(v.charAt(v.length() - 1) + ""))); assertEquals(map2.get("key1").get().intValue(), 1); 

6.2. Baumkarte


TreeMap ist eine Implementierung der SortedMap Schnittstelle. Wie bei TreeSet wird eine benutzerdefinierte Instanz von Comparator verwendet, um die Sortierung von TreeMap Elementen TreeMap .
SortedMap die Erstellung von SortedMap :

 SortedMap < Integer, String > map = TreeMap.of(3, "Three", 2, "Two", 4, "Four", 1, "One"); assertEquals(1, map.keySet().toJavaArray()[0]); assertEquals("Four", map.get(4).get()); 

Standardmäßig werden TreeMap Einträge in der Reihenfolge der natürlichen Schlüssel sortiert. Sie können jedoch den Comparator angeben, der zum Sortieren verwendet werden soll:

 TreeMap < Integer, String > treeMap2 = TreeMap.of(Comparator.reverseOrder(), 3, "three", 6, "six", 1, "one"); assertEquals(treeMap2.keySet().mkString(), "631"); 

Wie im Fall von TreeSet wird auch die TreeMap Implementierung unter Verwendung des Baums erstellt, daher haben ihre Operationen die Zeit O (log n) . Die map.get(key) -Methode gibt Option , die den Wert des angegebenen Map- Schlüssels enthält.

7. Java-Kompatibilität


Die Vavr Collection-API ist vollständig kompatibel mit dem Java Collection Framework. Mal sehen, wie das in der Praxis gemacht wird.

7.1. Konvertieren Sie von Java nach Vavr


Jede Auflistungsimplementierung in Vavr verfügt über eine statische Factory ofAll() -Methode, die java.util.Iterable akzeptiert. Auf diese Weise können Sie eine Vavr- Sammlung aus einer Java- Sammlung erstellen. In ähnlicher Weise akzeptiert eine andere ofAll() Factory-Methode direkt Java Stream .

So konvertieren Sie eine Java- List in eine unveränderliche List :

 java.util.List < Integer > javaList = java.util.Arrays.asList(1, 2, 3, 4); List < Integer > vavrList = List.ofAll(javaList); java.util.stream.Stream < Integer > javaStream = javaList.stream(); Set < Integer > vavrSet = HashSet.ofAll(javaStream); 

Eine weitere nützliche Funktion ist collector() , die in Verbindung mit Stream.collect() , um die Vavr-Sammlung abzurufen:

 List < Integer > vavrList = IntStream.range(1, 10) .boxed() .filter(i - > i % 2 == 0) .collect(List.collector()); assertEquals(4, vavrList.size()); assertEquals(2, vavrList.head().intValue()); 

7.2. Konvertieren Sie von Vavr nach Java


Die Value Schnittstelle verfügt über viele Methoden zum Konvertieren von einem Vavr- Typ in einen Java- Typ. Diese Methoden haben das Format toJavaXXX() .

Betrachten Sie einige Beispiele:

 Integer[] array = List.of(1, 2, 3) .toJavaArray(Integer.class); assertEquals(3, array.length); java.util.Map < String, Integer > map = List.of("1", "2", "3") .toJavaMap(i - > Tuple.of(i, Integer.valueOf(i))); assertEquals(2, map.get("2").intValue()); 

Wir können auch Java 8 Collectors , um Objekte aus Vavr-Sammlungen zu sammeln:

 java.util.Set < Integer > javaSet = List.of(1, 2, 3) .collect(Collectors.toSet()); assertEquals(3, javaSet.size()); assertEquals(1, javaSet.toArray()[0]); 

7.3. Java-Sammlungsansichten


Darüber hinaus bietet die Bibliothek sogenannte Sammlungsansichten , die bei der Konvertierung in Java-Sammlungen am besten funktionieren. Die Transformationsmethoden im vorherigen Abschnitt durchlaufen alle Elemente, um eine Java-Sammlung zu erstellen.

Ansichten hingegen implementieren Standard-Java-Schnittstellen und delegieren Methodenaufrufe an die Vavr-Basissammlung.

Zum Zeitpunkt dieses Schreibens wird nur die List unterstützt. Jede sequentielle Sammlung verfügt über zwei Methoden: eine zum Erstellen einer unveränderlichen Darstellung, die andere zum Ändern.

Das Aufrufen von Methoden zum Ändern einer unveränderlichen Ansicht UnsupportedOperationException .

Schauen wir uns ein Beispiel an:

 @Test(expected = UnsupportedOperationException.class) public void givenVavrList_whenViewConverted_thenException() { java.util.List < Integer > javaList = List.of(1, 2, 3) .asJava(); assertEquals(3, javaList.get(2).intValue()); javaList.add(4); } 

So erstellen Sie eine unveränderliche Ansicht:

 java.util.List < Integer > javaList = List.of(1, 2, 3) .asJavaMutable(); javaList.add(4); assertEquals(4, javaList.get(3).intValue()); 

8. Schlussfolgerungen


In diesem Tutorial haben wir die verschiedenen funktionalen Datenstrukturen kennengelernt, die von der Vavr Collections-API bereitgestellt werden. Es gibt auch nützliche und produktive API-Methoden, die im Java-Dokument und im Vavr Collections- Benutzerhandbuch enthalten sind .

Schließlich ist zu beachten, dass die Bibliothek auch Try , Option , Either und Future , wodurch die Value Schnittstelle erweitert und infolgedessen die Java Iterable Schnittstelle Iterable wird. Dies bedeutet, dass sie sich in einigen Situationen wie Sammlungen verhalten können.

Den vollständigen Quellcode für alle Beispiele in diesem Artikel finden Sie auf Github .

Zusätzliche Materialien:
habr.com/de/post/421839
www.baeldung.com/vavr

Übersetzt von @middle_java

Source: https://habr.com/ru/post/de474402/


All Articles