Vavr Collections Guide Guide

VAVR (المعروفة سابقًا باسم Javaslang) هي مكتبة وظيفية غير هادفة للربح لـ Java 8+. يتيح لك كتابة كود وظيفي يشبه Scala في Java ، ويعمل على تقليل مقدار الشفرة وتحسين جودتها. موقع المكتبة .

تحت القصاصة هي ترجمة لمقال منظم المعلومات على Vavr Collections API .

ترجم بواسطة middle_java

آخر تعديل للمقال الأصلي: 15 أغسطس 2019

1. نظرة عامة


مكتبة Vavr ، المعروفة سابقًا باسم Javaslang ، هي مكتبة وظيفية لجافا. في هذه المقالة ، نستكشف واجهة برمجة تطبيقات مجموعة قوية.

انظر هذه المقالة لمزيد من المعلومات حول هذه المكتبة.

2. المجموعات الثابتة


المجموعة الدائمة ، عند التعديل ، تنشئ نسخة جديدة من المجموعة دون تغيير الإصدار الحالي.

يمكن أن يؤدي دعم إصدارات متعددة من نفس المجموعة إلى الاستخدام غير الفعال لوحدة المعالجة المركزية والذاكرة. ومع ذلك ، فإن مكتبة مجموعة Vavr تتغلب على ذلك من خلال مشاركة بنية البيانات بين إصدارات مختلفة من المجموعة.

هذا يختلف اختلافًا جذريًا عن unmodifiableCollection() عن Collections فئات الأداة المساعدة Java ، والتي توفر ببساطة مجمّع للمجموعة الأساسية.

محاولة تعديل مثل هذه المجموعة UnsupportedOperationException بدلاً من إنشاء إصدار جديد. علاوة على ذلك ، لا تزال مجموعة الأساس قابلة للتغيير من خلال رابط مباشر لها.

3. قابلة للنقل


Traversable هو النوع الأساسي لجميع مجموعات Vavr. تحدد هذه الواجهة الطرق الشائعة لجميع هياكل البيانات.

يوفر بعض الطرق الافتراضية المفيدة ، مثل size() ، get() ، filter() ، isEmpty() وغيرها من isEmpty() التي يتم توارثها بواسطة واجهات فرعية.

نحن نستكشف مكتبة المجموعة.

4. بعد ذلك


لنبدأ بالتسلسلات.

واجهة Seq هي بنية بيانات متسلسلة. هذه هي الواجهة الرئيسية لـ List و Stream و Queue و Array و Vector و CharSeq . جميع هياكل البيانات هذه لها خصائصها الفريدة الخاصة بها ، والتي سنناقشها أدناه.

4.1. قائمة


List هي عبارة عن حساب محسوب (يتم تقييمه بشغف ، ويتم تنفيذ العملية بمجرد أن تصبح قيم LinearSeq معروفة) سلسلة من العناصر التي تمتد واجهة LinearSeq .

List الثابتة بشكل متكرر باستخدام الرأس والذيل :

  • الرأس هو العنصر الأول
  • الذيل - قائمة تحتوي على العناصر المتبقية (يتم تشكيل هذه القائمة أيضًا من الرأس والذيل)

تحتوي واجهة برمجة التطبيقات (API) على أساليب المصنع الثابتة التي يمكنك استخدامها لإنشاء List . يمكنك استخدام الأسلوب الثابت of() لإنشاء مثيل List من كائن واحد أو أكثر.

يمكنك أيضًا استخدام الأسلوب empty() الثابت empty() لإنشاء List فارغة وطريقة ofAll() لإنشاء List بالنوع ofAll() :

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

لنلقِ نظرة على بعض أمثلة التلاعب بالقائمة.

يمكننا استخدام طريقة drop() ومتغيراتها لإزالة العناصر N الأولى:

 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) بإزالة العناصر n من القائمة ، بدءًا من العنصر الأول ، بينما يقوم dropRight() نفسه ، بدءًا من العنصر الأخير في القائمة.

dropUntil() إزالة العناصر من القائمة إلى أن يكون المسند true ، بينما يقوم dropWhile() بإزالة العناصر إلى أن يكون المسند true .

هناك أيضًا dropRightWhile() و dropRightUntil() تزيل العناصر التي تبدأ من اليمين.

بعد ذلك ، take(int n) استخدام take(int n) لاسترداد العناصر من القائمة. يستغرق عناصر n من القائمة ثم يتوقف. يوجد أيضًا takeRight(int n) ، والذي يأخذ عناصر من نهاية القائمة:

 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); 

أخيرًا ، takeUntil() عناصر من القائمة حتى تصبح المسند true . هناك متغير من takeWhile() يأخذ أيضًا وسيطة أصلية.

بالإضافة إلى ذلك ، لدى واجهة برمجة التطبيقات طرقًا أخرى مفيدة ، على سبيل المثال ، حتى distinct() ، والتي تُرجع قائمة بالعناصر المكررة المحذوفة ، بالإضافة إلى distinctBy() ، والتي تقبل Comparator لتحديد المساواة.

من المثير للاهتمام أن هناك أيضًا intersperse() ، والتي تُدرج عنصرًا بين كل عنصر من عناصر القائمة. يمكن أن يكون هذا مناسبًا جدًا للعمليات باستخدام String :

 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"); 

هل تريد تقسيم القائمة إلى فئات؟ ولهذا هناك 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); 

تقوم طريقة group(int n) بتقسيم List إلى مجموعات من كل عنصر n . يقبل أسلوب groupdBy() Function تحتوي على منطق تقسيم القائمة وترجع Map مع عنصرين: true false .

يتم تعيين المفتاح true على List العناصر التي تفي بالشرط المحدد في Function . يعين المفتاح false إلى List العناصر التي لا تفي بهذا الشرط.

كما هو متوقع ، عند تغيير List ، لا تتغير List الأصلية بالفعل. بدلاً من ذلك ، List دائمًا إرجاع الإصدار الجديد من List .

يمكننا أيضًا التفاعل مع List باستخدام دلالات عناصر استخراج المكدس وفقًا لمبدأ "الأخير في الأول" (LIFO). وبهذا المعنى ، توجد طرق API مثل peek() و pop() و push() لمعالجة الرصة:

 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)); 

يتم استخدام وظيفة pushAll() لإدراج نطاق من الأعداد الصحيحة على المكدس ، ويتم استخدام وظيفة peek() لاسترداد عنصر الرأس من المكدس. هناك أيضًا طريقة peekOption() يمكنها التفاف النتيجة في كائن Option .

هناك طرق أخرى مفيدة ومفيدة حقًا في واجهة List والتي تم توثيقها تمامًا في مستندات Java .

4.2. طابور


تقوم Queue الثابتة بتخزين العناصر ، مما يتيح لك استردادها وفقًا لمبدأ FIFO (أولاً في ، أولاً خارج).

Queue داخل قائمتين مرتبطتين: القائمة الأمامية List الخلفية. تحتوي List الأمامية على عناصر تم إزالتها من قائمة الانتظار ، بينما تحتوي List الخلفية على عناصر في قائمة الانتظار.

يسمح لك هذا بوضع عمليات قائمة الانتظار والإزالة من قائمة الانتظار إلى التعقيد O (1) . عندما تنتهي List في List الأمامية عند إزالتها من قائمة الانتظار ، List عكس List الخلفية وتصبح القائمة الأمامية الجديدة.

لنقم بإنشاء قائمة انتظار:

 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))); 

تقوم وظيفة dequeue() بإزالة عنصر الرأس من Queue وإرجاع Tuple2<T, Q> . العنصر الأول في المجموعة هو عنصر الرأس الذي تمت إزالته من قائمة الانتظار ، والعنصر الثاني في المجموعة هو عناصر Queue المتبقية.

يمكننا استخدام combination(n) للحصول على جميع مجموعات N الممكنة من العناصر في Queue :

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

مرة أخرى ، لا يتغير Queue الأصلية أثناء إضافة / إزالة العناصر من قائمة الانتظار.

4.3. تيار


Stream هو تطبيق لقائمة مرتبطة بشكل كسول والتي تختلف اختلافًا كبيرًا عن java.util.stream . على عكس java.util.stream ، يقوم Stream Vavr بتخزين البيانات وحساب العناصر اللاحقة بتكاسل.
دعنا نقول لدينا أعداد صحيحة Stream :

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

عند طباعة نتيجة s.toString() في وحدة التحكم ، سيتم عرض الدفق فقط (2 ،؟) . هذا يعني أنه تم حساب عنصر رأس Stream فقط ، بينما لم يتم حساب عناصر الذيل.

يؤدي استدعاء s.get(3) ثم عرض نتيجة s.tail() إرجاع الدفق (1 ، 3 ، 4 ،؟) . على العكس من ذلك ، إذا لم تتصل بـ s.get(3) - مما سيجعل Stream يحسب العنصر الأخير - فقط ستريم (1 ،؟) سيكون نتيجة s.tail() ) . هذا يعني أنه تم حساب عنصر الذيل الأول فقط.

هذا السلوك يمكن أن يحسن الأداء ويسمح باستخدام Stream لتمثيل تسلسلات طويلة (نظريا) بلا حدود.
Stream في Vavr غير قابل للتغيير ويمكن أن يكون Empty أو Cons . Cons تتكون من عنصر الرأس والذيل محسوب كسول من Stream . بخلاف List ، يقوم Stream بتخزين عنصر الرأس Stream في الذاكرة. يتم حساب عناصر الذيل حسب الحاجة.

لنقم بإنشاء Stream من 10 أعداد صحيحة موجبة وحساب مجموع الأرقام الزوجية:

 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); 

على عكس API Stream من Java 8 ، يعد Stream in Vavr بنية بيانات لتخزين سلسلة من العناصر.

لذلك ، يحتوي على أساليب مثل get() ، و append() ، و insert() وغيرهم لمعالجة عناصره. drop() و distinct() وبعض الطرق الأخرى التي تمت مناقشتها مسبقًا.

أخيرًا ، دعنا tabulate() بسرعة tabulate() في Stream . تقوم هذه الطريقة بإرجاع Stream طوله n يحتوي على عناصر ناتجة عن تطبيق الوظيفة:

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

يمكننا أيضًا استخدام zip() لإنشاء Stream من Tuple2<Integer, Integer> ، والذي يحتوي على عناصر تم تشكيلها عن طريق الجمع بين Tuple2<Integer, Integer> :

 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 عبارة عن تسلسل مفهرس غير قابل للتغيير يوفر وصولًا عشوائيًا فعالًا. ويستند على مجموعة من الكائنات جافا. في جوهرها ، هذا عبارة عن مجمّع يمكن Traversable لمجموعة من الكائنات من النوع T

يمكنك إنشاء مثيل Array باستخدام طريقة of() الساكنة. بالإضافة إلى ذلك ، يمكنك إنشاء مجموعة من العناصر باستخدام range() الأساليب الثابتة range() و rangeBy() . يحتوي الأسلوب rangeBy() على معلمة ثالثة ، مما يسمح لك بتحديد الخطوة.

rangeBy() أساليب range() و rangeBy() عناصر ، تبدأ فقط من القيمة الأولية إلى القيمة النهائية مطروحًا منها واحدة. إذا كنا بحاجة إلى تضمين القيمة النهائية ، فيمكننا استخدام rangeClosed() أو 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); 

دعونا نعمل مع العناصر باستخدام الفهرس:

 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. سهم التوجيه


Vector عبارة عن تقاطع بين Array و List ، مما يوفر تسلسلًا آخر مفهرسًا للعناصر ، مما يتيح الوصول العشوائي والتعديل في وقت ثابت:

 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 هو كائن مجموعة لتمثيل سلسلة من الأحرف البدائية. في جوهرها ، هذا غلاف لـ String مع إضافة عمليات التجميع.

لإنشاء CharSeq يجب عليك القيام بما يلي.

 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. تعيين


يناقش هذا القسم التطبيقات المختلفة لـ Set في مكتبة المجموعة. تتمثل الميزة الفريدة لهيكل Set البيانات في أنه لا يسمح بقيم مكررة.

هناك العديد من تطبيقات Set . الرئيسي هو HashSet . لا يسمح TreeSet بالعناصر المكررة ويمكن فرزها. يحتفظ LinkedHashSet بترتيب الإدراج للعناصر.

دعونا نلقي نظرة فاحصة على هذه التطبيقات واحدة تلو الأخرى.

5.1. HashSet


لدى HashSet طرق مصنع ثابتة لإنشاء مثيلات جديدة. بعضها درسناه سابقًا في هذه المقالة ، على سبيل المثال of() ، ofAll() والاختلافات في أساليب range() .

يمكن الحصول على diff() بين المجموعتين باستخدام طريقة diff() . أيضًا ، تقوم intersect() union() intersect() بإرجاع الوحدة وتقاطع مجموعتين:

 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)); 

يمكننا أيضًا إجراء عمليات أساسية ، مثل إضافة عناصر وإزالتها:

 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")); 

يعتمد تطبيق HashSet على التعادل المعين لصفيف Hash (HAMT) ، والذي يتميز بأداء متفوق مقارنة بـ HashTable العادي وبنيته تجعله مناسبًا لدعم المجموعات المستمرة.

5.2. TreeSet


TreeSet غير قابل TreeSet هو تطبيق واجهة SortedSet . يقوم بتخزين مجموعة من العناصر المصنفة ويتم تنفيذه باستخدام أشجار البحث الثنائية. يتم تنفيذ جميع عملياتها خلال وقت O (log n) .

بشكل افتراضي ، يتم فرز عناصر TreeSet الطبيعي.
لنقم بإنشاء SortedSet باستخدام ترتيب فرز طبيعي:

 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()); 

لترتيب العناصر بطريقة مخصصة ، مرر مثيل Comparator عند إنشاء TreeSet . يمكنك أيضًا إنشاء سلسلة من مجموعة من العناصر:

 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 أيضًا على تطبيق BitSet غير قابل للتغيير. BitSet واجهة SortedSet على SortedSet واجهة SortedSet . يمكن إنشاء BitSet باستخدام أساليب ثابتة في BitSet.Builder .
كما هو الحال مع التطبيقات الأخرى الخاصة ببنية Set البيانات ، لا يسمح لك BitSet بإضافة سجلات مكررة إلى مجموعة.

يرث طرق المعالجة من واجهة Traversable . لاحظ أنه يختلف عن java.util.BitSet عن مكتبة Java القياسية. لا يمكن أن تحتوي بيانات BitSet على قيم String .

ضع في اعتبارك إنشاء مثيل لـ BitSet باستخدام أسلوب 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); 

لتحديد عناصر BitSet الأربعة الأولى BitSet استخدمنا الأمر takeUntil() . أرجعت العملية نسخة جديدة. لاحظ أن طريقة takeUntil() معرّفة في واجهة Traversable ، وهي الواجهة BitSet لـ BitSet .

تنطبق أيضًا الطرق والعمليات الأخرى الموضحة أعلاه في واجهة Traversable على BitSet .

6. خريطة


Map هي بنية بيانات ذات قيمة أساسية. Map في Vavr غير قابلة للتغيير ولديها تطبيقات HashMap و TreeMap و LinkedHashMap .

عادةً ، لا تسمح عقود الخريطة بمفاتيح مكررة ، بينما قد تكون القيم المكررة المعينة لمفاتيح مختلفة.

6.1. HashMap


HashMap هو تطبيق واجهة Map غير قابلة للتغيير. يقوم بتخزين أزواج المفاتيح ذات القيمة باستخدام مجموعة من المفاتيح.

تستخدم Map في Vavr Tuple2 لتمثيل أزواج القيمة الرئيسية بدلاً من نوع Entry التقليدي:

 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()); 

مثل HashSet ، يعتمد تطبيق HashMap على التعادل المعين لصفيف Hash (HAMT) ، مما يؤدي إلى وقت ثابت لجميع العمليات تقريبًا.
يمكن تصفية عناصر الخريطة بالمفتاح باستخدام طريقة filterKeys() أو حسب القيمة باستخدام طريقة filterValues() . كلتا الطريقتين تأخذ Predicate كوسيطة:

 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")); 

يمكنك أيضًا تحويل عناصر الخريطة باستخدام طريقة map() . على سبيل المثال ، دعنا تحويل map1 إلى 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. TreeMap


غير قابل للتغيير TreeMap هو تطبيق واجهة SortedMap . كما هو الحال مع TreeSet ، Comparator استخدام مثيل مخصص لـ Comparator لتخصيص فرز عناصر TreeMap .
SortedMap إنشاء 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()); 

بشكل افتراضي ، يتم فرز إدخالات TreeMap بترتيب المفتاح الطبيعي. ومع ذلك ، يمكنك تحديد Comparator لاستخدامها في الفرز:

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

كما هو الحال في TreeSet ، يتم أيضًا إنشاء تطبيق TreeMap باستخدام الشجرة ، وبالتالي فإن عملياته لها وقت O (log n) . ترجع طريقة map.get(key) Option ، الذي يحتوي على قيمة مفتاح الخريطة المحدد.

7. توافق جافا


واجهة برمجة تطبيقات Vavr Collection API متوافقة تمامًا مع Java Collection Framework. دعونا نرى كيف يتم ذلك في الممارسة العملية.

7.1. تحويل من جافا إلى Vavr


يحتوي كل تطبيق مجموعة في Vavr على أسلوب ثابت لـ ofAll() يقبل java.util.Iterable . هذا يسمح لك بإنشاء مجموعة Vavr من مجموعة Java . وبالمثل ، فإن طريقة مصنع ofAll() تقبل مباشرة Java Stream .

لتحويل List Java إلى 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); 

وظيفة أخرى مفيدة هي collector() ، والذي يمكن استخدامه مع Stream.collect() للحصول على مجموعة Vavr:

 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. تحويل من Vavr إلى جافا


تحتوي واجهة Value على العديد من الطرق للتحويل من نوع Vavr إلى نوع Java . هذه الطرق لها التنسيق toJavaXXX() .

النظر في بعض الأمثلة:

 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()); 

يمكننا أيضًا استخدام Java 8 Collectors لجمع العناصر من مجموعات Vavr:

 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. تقوم أساليب التحويل في القسم السابق بتكرار (تكرار) جميع العناصر لإنشاء مجموعة Java.

المشاهدات ، من ناحية أخرى ، تقوم بتنفيذ واجهات Java القياسية وتفويض استدعاءات الطريقة لمجموعة Vavr base.

في وقت كتابة هذا التقرير ، كان يتم دعم طريقة عرض List فقط. كل مجموعة متسلسلة لها طريقتان: واحدة لإنشاء تمثيل ثابت ، والآخر قابل للتغيير.

استدعاء أساليب للتغيير على طريقة عرض غير قابلة للتغيير UnsupportedOperationException .

لنلقِ نظرة على مثال:

 @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); } 

لإنشاء طريقة عرض غير قابلة للتغيير:

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

8. الاستنتاجات


في هذا البرنامج التعليمي ، علمنا بهياكل البيانات الوظيفية المختلفة التي يوفرها Vavr Collections API. هناك أيضًا طرق API مفيدة ومثمرة يمكن العثور عليها في Java doc ودليل مستخدم Vavr Collections.

أخيرًا ، من المهم ملاحظة أن المكتبة تعرّف أيضًا " Try و " Option و " Either و " Future ، والتي تعمل على توسيع واجهة " Value ، ونتيجة لذلك ، تقوم بتنفيذ واجهة Java Iterable . وهذا يعني أنه في بعض المواقف يمكن أن يتصرفوا مثل المجموعات.

يمكن العثور على شفرة المصدر الكاملة لجميع الأمثلة في هذه المقالة على جيثب .

مواد إضافية:
habr.com/ru/post/421839
www.baeldung.com/vavr

ترجم بواسطة middle_java

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


All Articles