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_javaLetzter 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
TSie 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/421839www.baeldung.com/vavrÜbersetzt von
@middle_java