BT

Diffuser les Connaissances et l'Innovation dans le Développement Logiciel d'Entreprise

Contribuez

Sujets

Sélectionner votre région

Accueil InfoQ Actualités Eclipse Collections 11.0.0 Présente De Nouvelles API Et Fonctionnalités

Eclipse Collections 11.0.0 Présente De Nouvelles API Et Fonctionnalités

La publication d'Eclipse Collections 11.0.0, une bibliothèque de collections open source pour Java compatible avec les types de collections Java, fournit de nouvelles méthodes et des fonctionnalités pour de meilleures performances. La classe ClassComparer a été introduite pour comparer les méthodes de deux classes et afficher les similitudes et les différences.

Initialement nommé GS Collections par son créateur Don Raab, le framework a été donné à la Fondation Eclipse en décembre 2015 et rebaptisé Eclipse Collections. La version 11.0.0 est la première version depuis la version 10.4 en août 2020. Eclipse Collections, maintenue par ces committers et chefs de projet, est construit et testé avec les JDK 8, 11, 17 et 18 early access.

Diverses méthodes, telles que selectWithIndex et rejectWithIndex, ont été ajoutées pour filtrer les éléments en fonction de l'index et de la valeur d'un OrderedIterable ou 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);

Les primitives itérables peuvent être converties en une MutableList avec soit la méthode toSortedList avec un Comparator en argument ou la méthode toSortedListBy en fournissant une Function :

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

Diverses méthodes, comme détaillé par Sirisha Pratha dans partie 1 et partie 2 de sa série de blogs, ont été ajoutés à Set. La première méthode, union, combine les éléments de deux ensembles :

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

La méthode intersect sélectionne les éléments présents dans les deux ensembles :

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

Une autre nouvelle méthode, difference, conserve les éléments uniques du premier ensemble :

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

La méthode symmetricDifference conserve les éléments qui sont uniques dans l'un des deux ensembles :

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

La méthode isSubsetOf renvoie true si tous les éléments du premier ensemble sont présents dans le second ensemble :

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

La version plus stricte, isProperSubsetOf, renvoie true si tous les éléments du premier ensemble sont présents dans le second ensemble, mais les ensembles ne sont pas égaux :

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

La méthode cartesianProduct renvoie toutes les paires ordonnées où le premier élément provient de la paire du premier ensemble et le deuxième élément provient du deuxième ensemble :

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

Les méthodes nouvellement introduites, containsAny et containsNone pour les collections primitives, offrent des avantages en termes de performances par rapport à l'équivalent fonctionnel anySatisfy et noneSatisfy moyennant un coût mémoire :

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 et Triple contiennent maintenant les méthodes isEqual et isSame par défaut pour comparer les valeurs :

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

En plus de comparer les valeurs, il est également désormais possible de convertir Paire et Triple en plusieurs types de List :

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

Un Bag est une collection non ordonnée qui peut contenir des doublons. Il est principalement utilisé pour déterminer et supprimer le nombre d'occurrences par élément. Cette version fournit plusieurs nouvelles méthodes pour Bag qui sont démontrés sur la base de l'exemple suivant :

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

Il est désormais possible de vérifier si le Bag contient un élément :

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

Ou si le Bag contient un élément spécifique avec le nombre d'occurrences spécifié :

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

Ou vérifier s'il existe des éléments avec un nombre spécifique d'occurrences :

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

Collectors2 contient désormais la méthode 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 fournit également les méthodes toImmutableSortedMap, toImmutableSortedMapBy, toSortedMap et 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);

Avec les nouvelles méthodes newWithMap et newWithMapIterable sur ImmutableMap, il est possible de créer des maps immuables :

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

Les méthodes withMapIterable et putAllMapIterable ont été ajoutées à MutableMap pour la cohérence.

Le module eclipse-collections-testutils contient maintenant la classe ClassComparer pour comparer des classes. Cela se traduit par une sorte de diagramme de Venn affichant les méthodes communes et les méthodes spécifiques à la classe, qui peuvent éventuellement être affichées avec une interface utilisateur Swing expérimentale. La comparaison de IntIterable.class et RichIterable.class affiche les résultats suivants, qui ne contiennent que des méthodes commençant par 'a' pour la lisibilité :

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]
…

Alternativement, ClassComparer offre un argument de constructeur pour éventuellement comparer en fonction des noms de méthodes, des types de paramètres et des types de retour :

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]
…

Les méthodes de conversion mutables, telles que toList et toSortedSet, sont disponibles depuis un certain temps, mais leurs homologues immuables n'étaient pas disponibles. Il était cependant possible de convertir en immuable en utilisant la méthode toImmutable, mais nécessitait parfois deux étapes : .toList().toImmutable(). Pour améliorer la cohérence avec les homologues mutables, toImmutableList, toImmutableSet et toImmutableBag ont été ajoutées à RichIterable et d'autres méthodes pourraient suivre à l'avenir.

La liste complète des modifications est disponible sur la page GitHub de la release.

 

Au sujet de l’Auteur

Evaluer cet article

Pertinence
Style

Contenu Éducatif

BT