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/421839www.baeldung.com/vavrترجم بواسطة
middle_java