انتشار مجموعه‌های Eclipse 11.0.0، یک کتابخانه مجموعه‌های منبع باز برای جاوا که با انواع مجموعه جاوا سازگار است، روش‌ها و قابلیت‌های جدیدی را برای بهبود عملکرد فراهم می‌کند. ClassComparer برای مقایسه روش های دو کلاس و نمایش شباهت ها و تفاوت ها معرفی شد.

این فریم ورک که در ابتدا توسط خالق آن دان راب، مجموعه‌های GS نامگذاری شد، در دسامبر ۲۰۱۵ به بنیاد اکلیپس اهدا شد و به مجموعه‌های اکلیپس تغییر نام داد. نسخه 11.0.0 اولین نسخه بعد از نسخه 10.4 در آگوست 2020 است. Eclipse Collection که توسط این committer ها و سرنخ های پروژه نگهداری می شود، ساخته شده و در برابر دسترسی اولیه JDK 8، 11، 17 و 18 آزمایش شده است.

روش‌های مختلفی مانند selectWithIndex و rejectWithIndex به عناصر فیلتر بر اساس شاخص و مقدار OrderedIterable یا ListIterable اضافه شدند:

var exampleList = Lists.mutable.with(1, 2, 3, 4, 5);
var selectWithIndexList = 
    exampleList.selectWithIndex((value, index) -> value + index < 6);
assertEquals(Lists.mutable.with(1, 2, 3), selectWithIndexList);

var rejectWithIndexList = 
    exampleList.rejectWithIndex((value, index) -> value + index < 6);
assertEquals(Lists.mutable.with(4,5), rejectWithIndexList);

تکرار پذیرهای اولیه ممکن است با ارائه یک تابع به یک MutableList با toSortedList با یک مقایسه کننده به عنوان آرگومان یا toSortedListBy تبدیل شوند:

var exampleSet = Sets.mutable.with(1, 2, 3, 4, 5);
var sortedList = exampleSet.toSortedList((val1, val2) -> val2 - val1);
var expected = Lists.mutable.with(5, 4, 3, 2, 1);
assertEquals(expected, sortedList);

var sortedListBy = exampleSet.toSortedListBy(Math::negateExact);
assertEquals(expected, sortedListBy);

روش‌های مختلفی که سیریشا پراتا در قسمت 1 و قسمت 2 مجموعه وبلاگ خود شرح داده است، به مجموعه اضافه شد. روش اول، اتحاد، عناصر را از دو مجموعه ترکیب می کند:

var set1 = Sets.mutable.with(1, 2, 3);
var set2 = Sets.mutable.with(3, 4, 5);
var expectedSet = Sets.mutable.with(1, 2, 3, 4, 5);
assertEquals(expectedSet, set1.union(set2));

متد intersect عناصر موجود در هر دو مجموعه را انتخاب می کند:

var set1 = Sets.mutable.with(1, 2, 3);
var set2 = Sets.mutable.with(3, 4, 5);
var expectedSet = Sets.mutable.with(3);
assertEquals(expectedSet, set1.intersect(set2));

روش جدید دیگر، تفاوت، عناصر منحصر به فرد مجموعه اول را حفظ می کند:

var set1 = Sets.mutable.with(1, 2, 3);
var set2 = Sets.mutable.with(3, 4, 5);
var expectedSet = Sets.mutable.with(1, 2);
assertEquals(expectedSet, set1.difference(set2));

روش SymmetricDifference عناصری را که منحصر به فرد هستند در یکی از دو مجموعه نگه می دارد:

var set1 = Sets.mutable.with(1, 2, 3);
var set2 = Sets.mutable.with(3, 4, 5);
var expectedSet = Sets.mutable.with(1, 2, 4, 5);
assertEquals(expectedSet, set1.symmetricDifference(set2));

اگر تمام عناصر مجموعه اول در مجموعه دوم وجود داشته باشند، متد isSubsetOf مقدار true را برمی گرداند:

var set1 = Sets.mutable.with(1, 2);
var set2 = Sets.mutable.with(1, 2, 3);
assertTrue(set1.isSubsetOf(set2));
assertFalse(set2.isSubsetOf(set1));

نسخه سخت‌تر، isProperSubsetOf، اگر همه عناصر مجموعه اول در مجموعه دوم وجود داشته باشند، اما مجموعه‌ها برابر نباشند، true را برمی‌گرداند:

var set1 = Sets.mutable.with(1, 2);
var set2 = Sets.mutable.with(1, 2, 3);
assertTrue(set1.isProperSubsetOf(set2));

var set3 = Sets.mutable.with(1, 2);
assertFalse(set1.isProperSubsetOf(set3));

متد CartesianProduct تمام جفت‌های مرتب شده را برمی‌گرداند که عنصر اول از جفت مجموعه اول و عنصر دوم از مجموعه دوم آمده است:

var set1 = IntSets.mutable.with(1, 2);
var set2 = IntSets.mutable.with(3, 4);

MutableSet<IntIntPair> expected = Sets.mutable.with(
    PrimitiveTuples.pair(1, 3),
    PrimitiveTuples.pair(1, 4),
    PrimitiveTuples.pair(2, 4),
    PrimitiveTuples.pair(2, 3));
assertEquals(expected, set1.cartesianProduct(set2).toSet());

روش‌های جدید معرفی شده، containAny و containNone برای مجموعه‌های اولیه، مزایای عملکردی را برای معادل عملکردی anySatisfy و noneSatisfy با هزینه حافظه ارائه می‌کنند:

ImmutableIntList list = IntLists.immutable.of(1, 2, 3, 4, 5);
assertTrue(list.containsAny(3, 6));
assertTrue(list.containsAny(new IntArrayList(3, 6)));

assertTrue(list.containsNone(6, 8));
assertTrue(list.containsNone(new IntArrayList(6, 8)));

Pair و Triple اکنون حاوی متدهای پیش فرض isEqual و isSame برای مقایسه مقادیر هستند:

Twin<String> equalTwin = Tuples.twin("James", "James");
assertTrue(equalTwin.isEqual());

Triplet<String> equalTriplet = Tuples.triplet("James", "James", "James");
assertTrue(equalTriplet.isEqual());

Twin<String> sameTwin = Tuples.twin("James", new String("James"));
assertFalse(sameTwin.isSame());

Triplet<String> sameTriplet = 
    Tuples.triplet("James", "James", new String("James"));
assertFalse(sameTriplet.isSame());

در کنار مقایسه مقادیر، اکنون امکان تبدیل Pair و Triple به چندین نوع لیست نیز وجود دارد:

n<String> twin = Tuples.twin("James", "Mike");
MutableList<String> pairMutableList = Tuples.pairToList(twin);
FixedSizeList<String> pairFixedSizeList = Tuples.pairToFixedSizeList(twin);
ImmutableList<String> pairImmutableList = Tuples.pairToImmutableList(twin);

Triplet<String> triplet = Tuples.triplet("James", "Mike", "Patrick");
MutableList<String> tripletMutableList = Tuples.tripleToList(triplet);
FixedSizeList<String> tripletFixedSizeList = 
    Tuples.tripleToFixedSizeList(triplet);
ImmutableList<String> tripletImmutableList = 
    Tuples.tripleToImmutableList(triplet);

کیسه یک مجموعه نامرتب است که ممکن است حاوی موارد تکراری باشد. بیشتر برای تعیین و حذف تعداد وقوع در هر مورد استفاده می شود. این نسخه چندین روش جدید برای Bag ارائه می دهد که بر اساس مثال زیر نشان داده شده است:

Bag<String> names = Bags.mutable.with("James", "James", "Mike", "Patrick");

اکنون می توان بررسی کرد که آیا کیف حاوی یک مورد است یا خیر:

assertTrue(names.anySatisfyWithOccurrences((object, value) ->
object.equals("Mike")));
assertTrue(names.noneSatisfyWithOccurrences((object, value) ->
    object.equals("Simon")));

یا اگر کیسه حاوی یک مورد خاص با تعداد دفعات مشخص شده باشد:

assertTrue(names.anySatisfyWithOccurrences((object, value) ->
    object.equals("James") && value == 2));
assertTrue(names.noneSatisfyWithOccurrences((object, value) ->
    object.equals("James") && value == 1));

یا بررسی کنید که آیا مواردی با تعداد تکرار مشخص وجود دارد:

assertTrue(names.anySatisfyWithOccurrences((object, value) ->
    value == 2));
assertTrue(names.noneSatisfyWithOccurrences((object, value) ->
    value > 3));

Collectors2 اکنون حاوی متد toImmutableSortedBagBy است:

var exampleList = Lists.mutable.with(1, 2, 3, 4);
ImmutableSortedBag<Integer> bag = exampleList.stream()
    .collect(Collectors2.toImmutableSortedBagBy(Math::negateExact));

Comparator<Integer> comparator = Functions.toIntComparator(Math::negateExact);
ImmutableSortedMap<Integer, Integer> immutableSortedMap = exampleList.stream()
    .collect(Collectors2.toImmutableSortedMap(comparator, element -> element, element -> element * 2));
var expected = SortedMaps.mutable.with(comparator, 4, 8, 3, 6, 2, 4, 1, 2);
assertEquals(expected, immutableSortedMap);

Collectors2 همچنین متدهای toImmutableSortedMap، toImmutableSortedMapBy، toSortedMap و toSortedMapBy را ارائه می دهد:

List<Integer> list = List.of(1, 2, 3);
Comparator<Integer> c =
    Functions.toIntComparator(Math::negateExact);
MutableSortedMap<Integer, String> map =
    list.stream().collect(
        Collectors2.toSortedMap(c, e -> e, String::valueOf));
var expected = SortedMaps.mutable.with(c, 1, "1", 2, "2", 3, "3");
assertEquals(expected, map);

با توابع جدید newWithMap و newWithMapIterable در ImmutableMap، می توان نقشه های تغییرناپذیر ایجاد کرد:

ImmutableMap<String, Integer> immutableMap = Maps.immutable.empty();
ImmutableMap<String, Integer> resultingImmutableMap = 
    immutableMap.newWithMap(UnifiedMap.newMapWith(
        Tuples.pair("Simon", 1),
        Tuples.pair("Mike", 2)));

ImmutableMapIterable<String, Integer> immutableMapIterable = 
    Maps.immutable.empty();
ImmutableMapIterable<String, Integer> resultingImmutableMapIterable = 
    immutableMap.newWithMapIterable(UnifiedMap.newMapWith(
        Tuples.pair("Simon", 1),
        Tuples.pair("Mike", 2)));

متدهای withMapIterable و putAllMapIterable برای سازگاری به MutableMap اضافه شدند.

ماژول eclipse-collections-testutils اکنون حاوی ClassComparer برای مقایسه کلاس ها است. این امر منجر به نوعی نمودار Venn می شود که روش های رایج و روش های کلاس خاص را نشان می دهد، که به صورت اختیاری ممکن است با یک رابط کاربری Swing آزمایشی نمایش داده شود. مقایسه IntIterable.class و RichIterable.class نتایج زیر را نشان می دهد که فقط شامل متدهایی هستند که برای خوانایی با “a” شروع می شوند:

new ClassComparer().compareAndPrint(IntIterable.class, RichIterable.class);
Intersection (IntIterable, RichIterable)
----------------------------------------
a:[allSatisfy, anySatisfy, appendString, asLazy]
…

Difference (IntIterable, RichIterable)
--------------------------------------
a:[average, averageIfEmpty]
…

Difference (RichIterable, IntIterable)
--------------------------------------
a:[aggregateBy, aggregateInPlaceBy, allSatisfyWith, anySatisfyWith]

از طرف دیگر، ClassComparer یک آرگومان سازنده برای مقایسه اختیاری بر اساس نام متدها، انواع پارامترها و انواع برگشتی ارائه می دهد:

new ClassComparer(true, true, true)
    .compareAndPrint(IntIterable.class, RichIterable.class);
Intersection (org.eclipse.collections.api.IntIterable, org.eclipse.collections.api.RichIterable)
------------------------------------------------------------------------------------------------
a:[appendString(Appendable):void, appendString(Appendable, String):void, appendString(Appendable, String, String, String):void]
…

Difference (org.eclipse.collections.api.IntIterable, org.eclipse.collections.api.RichIterable)
----------------------------------------------------------------------------------------------
a:[allSatisfy(IntPredicate):boolean, anySatisfy(IntPredicate):boolean, asLazy():LazyIntIterable, average():double, averageIfEmpty(double):double]
…

Difference (org.eclipse.collections.api.RichIterable, org.eclipse.collections.api.IntIterable)
----------------------------------------------------------------------------------------------
a:[aggregateBy(Function, Function0, Function2):MapIterable, aggregateBy(Function, Function0, Function2, MutableMapIterable):MutableMapIterable, aggregateInPlaceBy(Function, Function0, Procedure2):MapIterable, allSatisfy(Predicate):boolean, allSatisfyWith(Predicate2, Object):boolean, anySatisfy(Predicate):boolean, anySatisfyWith(Predicate2, Object):boolean, asLazy():LazyIterable]

روش‌های مبدل قابل تغییر، مانند toList و toSortedSet، مدت‌هاست که در دسترس بوده‌اند، اما همتاهای غیرقابل تغییر آن‌ها در دسترس نبودند. با این حال، تبدیل به غیرقابل تغییر با استفاده از روش toImmutable امکان پذیر بود، اما گاهی اوقات به دو مرحله نیاز بود: .toList().toImmutable(). برای بهبود سازگاری با همتاهای قابل تغییر، toImmutableList، toImmutableSet و toImmutableBag به RichIterable اضافه شدند و روش‌های دیگری ممکن است در آینده دنبال شوند.

لیست کامل تغییرات در صفحه GitHub موجود است.