Introduction aux collections Eclipse

Introduction aux collections Eclipse

1. Vue d'ensemble

Eclipse Collections est un autre framework de collecte amélioré pour Java.

En termes simples, il fournit des implémentations optimisées ainsi que des structures de données et des fonctionnalités supplémentaires qui n’existent pas dans le noyau Java.

La bibliothèque fournit des implémentations mutables et immuables de toutes les structures de données.

2. Dépendance Maven

Commençons par ajouter la dépendance Maven suivante à nospom.xml:

org.eclipse.collections
    eclipse-collections
    8.2.0

Nous pouvons trouver la dernière version de la bibliothèque dans leMaven Central Repository.

3. La grande image

3.1. Types de collection de base

Les types de collection de base dans Eclipse Collections sont les suivants:

  • ListIterable - une collection ordonnée qui maintient l'ordre d'insertion et autorise la duplication des éléments. Les sous-interfaces incluent:MutableList,FixedSizeList etImmutableList. LesListIterable implementation is FastList, which is a subclass of MutableList les plus courants

  • SetIterable - une collection qui n'autorise aucun élément en double. Il peut être trié ou non trié. Les sous-interfaces incluent:SortedSetIterable etUnsortedSetIterable. L'implémentation non triée la plus courante deSetIterable estUnifiedSet

  • MapIterable - une collection de paires clé / valeur. Les sous-interfaces incluentMutableMap,FixedSizeMap etImmutableMap. Deux implémentations courantes sontUnifiedMap etMutableSortedMap. Alors queUnifiedMap ne maintient aucun ordre,MutableSortedMap maintient l'ordre naturel des éléments

  • BiMap - une collection de paires clé / valeur qui peuvent être itérées dans les deux sens. BiMap étend l'interfaceMapIterable

  • Bag - une collection non ordonnée qui autorise les doublons. Les sous-interfaces incluentMutableBag andFixedSizeBag. L'implémentation la plus courante estHashBag

  • StackIterable - une collection qui maintient l'ordre «dernier entré, premier sorti», en parcourant les éléments dans l'ordre d'insertion inverse. Les sous-interfaces incluentMutableStack etImmutableStack

  • MultiMap - une collection de paires clé / valeur qui autorise plusieurs valeurs pour chaque clé

3.2. Collections primitives

The framework also provides a huge set of primitive collections; leurs implémentations sont nommées d'après le type qu'elles détiennent. Il existe des formes mutables, immuables, synchronisées et non modifiables pour chaque type:

  • PrimitiveLists

  • PrimitiveSets

  • PrimitiveStacks

  • PrimitiveBags

  • PrimitiveMaps

  • IntInterval

Il existe un grand nombre de formes de carte primitives couvrant toutes les combinaisons possibles de clés primitives ou d'objet et de valeurs primitives ou d'objet.

Une note rapide - unIntInterval est une plage d'entiers qui peut être itérée en utilisant une valeur de pas.

4. Instancier une collection

Pour ajouter des éléments à unArrayList ouHashSet, nous instancions une collection en appelant le constructeur no-arg, puis en ajoutant chaque élément un par un.

Bien que nous puissions encore le faire dans les collections Eclipse,we can also instantiate a collection and provide all initial elements at the same time in a single line.

Voyons comment nous pouvons instancier unFastList:

MutableList list = FastList.newListWith(
  "Porsche", "Volkswagen", "Toyota", "Mercedes", "Toyota");

De même, nous pouvons instancier unUnifiedSet et y ajouter des éléments en passant les éléments à la méthode statiquenewSetWith():

Set comparison = UnifiedSet.newSetWith(
  "Porsche", "Volkswagen", "Toyota", "Mercedes");

Voici comment nous pouvons instancier unHashBag:

MutableBag bag = HashBag.newBagWith(
  "Porsche", "Volkswagen", "Toyota", "Porsche", "Mercedes");

L'instanciation de cartes et l'ajout de paires clé / valeur sont similaires. La seule différence est que nous transmettons les paires clé et valeur à la méthodenewMapWith() en tant qu'implémentations de l'interfacePair.

PrenonsUnifiedMap comme exemple:

Pair pair1 = Tuples.pair(1, "One");
Pair pair2 = Tuples.pair(2, "Two");
Pair pair3 = Tuples.pair(3, "Three");

UnifiedMap map = new UnifiedMap<>(pair1, pair2, pair3);

Nous pouvons toujours utiliser l'approche API Java Collections:

UnifiedMap map = new UnifiedMap<>();

map.put(1, "one");
map.put(2, "two");
map.put(3, "three");

Depuisimmutable collections cannot be modified, they do not have implementations of methods that modify collections commeadd() etremove().

Les collections non modifiables, cependant, nous permettent d'appeler ces méthodes mais jetteront unUnsupportedOperationException si nous le faisons.

5. Récupération d'éléments à partir de collections

Tout comme l'utilisation desLists standard, les éléments des collections EclipseLists peuvent être récupérés par leur index:

list.get(0);

Et les valeurs des cartes Eclipse Collections peuvent être récupérées à l'aide de leur clé:

map.get(0);

Les méthodesgetFirst() etgetLast() peuvent être utilisées pour récupérer respectivement le premier et le dernier élément d'une liste. Dans le cas d'autres collections, elles renvoient le premier et le dernier élément qui seraient retournés par un itérateur.

map.getFirst();
map.getLast();

Les méthodesmax() etmin() peuvent être utilisées pour obtenir les valeurs maximum et minimum d'une collection basée sur l'ordre naturel.

map.max();
map.min();

6. Itérer sur une collection

Les collections Eclipse offrent de nombreuses façons de parcourir les collections. Voyons ce qu’ils sont et comment ils fonctionnent dans la pratique.

6.1. Filtrage des collections

Le modèle sélectionné renvoie une nouvelle collection contenant des éléments d’une collection qui satisfont à une condition logique. C'est essentiellement une opération de filtrage.

Voici un exemple:

@Test
public void givenListwhenSelect_thenCorrect() {
    MutableList greaterThanThirty = list
      .select(Predicates.greaterThan(30))
      .sortThis();

    Assertions.assertThat(greaterThanThirty)
      .containsExactly(31, 38, 41);
}

La même chose peut être faite en utilisant une simple expression lambda:

return list.select(i -> i > 30)
  .sortThis();

Le schéma de rejet est le contraire. Il renvoie une collection de tous les éléments qui ne satisfont pas à une condition logique.

Voyons un exemple:

@Test
public void whenReject_thenCorrect() {
    MutableList notGreaterThanThirty = list
      .reject(Predicates.greaterThan(30))
      .sortThis();

    Assertions.assertThat(notGreaterThanThirty)
      .containsExactlyElementsOf(this.expectedList);
}

Ici, nous rejetons tous les éléments supérieurs à 30.

6.2. La méthodecollect()

La méthodecollect renvoie une nouvelle collection dont les éléments sont les résultats renvoyés par l'expression lambda fournie - il s'agit essentiellement d'une combinaison desmap() etcollect() de l'API Stream.

Voyons cela en action:

@Test
public void whenCollect_thenCorrect() {
    Student student1 = new Student("John", "Hopkins");
    Student student2 = new Student("George", "Adams");

    MutableList students = FastList
      .newListWith(student1, student2);

    MutableList lastNames = students
      .collect(Student::getLastName);

    Assertions.assertThat(lastNames)
      .containsExactly("Hopkins", "Adams");
}

La collection crééelastNames contient les noms de famille qui sont collectés dans la listestudents.

Mais,what if the returned collection is a collection of collections and we do not want to maintain a nested structure?

Par exemple, si chaque étudiant a plusieurs adresses et que nous avons besoin d'une collection qui contient les adresses en tant queStrings plutôt qu'une collection de collections, nous pouvons utiliser la méthodeflatCollect().

Voici un exemple:

@Test
public void whenFlatCollect_thenCorrect() {
    MutableList addresses = students
      .flatCollect(Student::getAddresses);

    Assertions.assertThat(addresses)
      .containsExactlyElementsOf(this.expectedAddresses);
}

6.3. Détection d'élément

La méthodedetect trouve et renvoie le premier élément qui satisfait une condition logique.

Prenons un exemple rapide:

@Test
public void whenDetect_thenCorrect() {
    Integer result = list.detect(Predicates.greaterThan(30));

    Assertions.assertThat(result)
      .isEqualTo(41);
}

La méthodeanySatisfy détermine si un élément d'une collection satisfait une condition logique.

Voici un exemple:

@Test
public void whenAnySatisfiesCondition_thenCorrect() {
    boolean result = list.anySatisfy(Predicates.greaterThan(30));

    assertTrue(result);
}

De même, la méthodeallSatisfy détermine si tous les éléments d'une collection satisfont à une condition logique.

Voyons un exemple rapide:

@Test
public void whenAnySatisfiesCondition_thenCorrect() {
    boolean result = list.allSatisfy(Predicates.greaterThan(0));

    assertTrue(result);
}

6.4. La méthodepartition()

La méthodepartition alloue chaque élément d'une collection dans l'une des deux collections selon que l'élément satisfait ou non à une condition logique.

Voyons un exemple:

@Test
public void whenAnySatisfiesCondition_thenCorrect() {
    MutableList numbers = list;
    PartitionMutableList partitionedFolks = numbers
      .partition(i -> i > 30);

    MutableList greaterThanThirty = partitionedFolks
      .getSelected()
      .sortThis();
    MutableList smallerThanThirty = partitionedFolks
      .getRejected()
      .sortThis();

    Assertions.assertThat(smallerThanThirty)
      .containsExactly(1, 5, 8, 17, 23);
    Assertions.assertThat(greaterThanThirty)
      .containsExactly(31, 38, 41);
}

6.5. Itération paresseuse

L'itération différée est un modèle d'optimisation dans lequel une méthode d'itération est appelée, mais son exécution réelle est différée jusqu'à ce que son action ou ses valeurs de retour soient requises par une autre méthode ultérieure.

@Test
public void whenLazyIteration_thenCorrect() {
    Student student1 = new Student("John", "Hopkins");
    Student student2 = new Student("George", "Adams");
    Student student3 = new Student("Jennifer", "Rodriguez");

    MutableList students = Lists.mutable
      .with(student1, student2, student3);
    LazyIterable lazyStudents = students.asLazy();
    LazyIterable lastNames = lazyStudents
      .collect(Student::getLastName);

    Assertions.assertThat(lastNames)
      .containsAll(Lists.mutable.with("Hopkins", "Adams", "Rodriguez"));
}

Ici, l'objetlazyStudents ne récupère pas les éléments de la listestudents tant que la méthodecollect() n'est pas appelée.

7. Association d'éléments de collection

La méthodezip() renvoie une nouvelle collection en combinant les éléments de deux collections en paires. Si l'une des deux collections est plus longue, les éléments restants seront tronqués.

Voyons comment nous pouvons l'utiliser:

@Test
public void whenZip_thenCorrect() {
    MutableList numbers = Lists.mutable
      .with("1", "2", "3", "Ignored");
    MutableList cars = Lists.mutable
      .with("Porsche", "Volvo", "Toyota");
    MutableList> pairs = numbers.zip(cars);

    Assertions.assertThat(pairs)
      .containsExactlyElementsOf(this.expectedPairs);
}

Nous pouvons également associer les éléments d’une collection à leurs index en utilisant la méthodezipWithIndex():

@Test
public void whenZip_thenCorrect() {
    MutableList cars = FastList
      .newListWith("Porsche", "Volvo", "Toyota");
    MutableList> pairs = cars.zipWithIndex();

    Assertions.assertThat(pairs)
      .containsExactlyElementsOf(this.expectedPairs);
}

8. Conversion de collections

Eclipse Collections fournit des méthodes simples pour convertir un type de conteneur en un autre. Ces méthodes sonttoList(),toSet(),toBag() ettoMap().

Voyons comment nous pouvons les utiliser:

public static List convertToList() {
    UnifiedSet cars = new UnifiedSet<>();

    cars.add("Toyota");
    cars.add("Mercedes");
    cars.add("Volkswagen");

    return cars.toList();
}

Lançons notre test:

@Test
public void whenConvertContainerToAnother_thenCorrect() {
    MutableList cars = (MutableList) ConvertContainerToAnother
      .convertToList();

    Assertions.assertThat(cars)
      .containsExactlyElementsOf(
      FastList.newListWith("Volkswagen", "Toyota", "Mercedes"));
}

9. Conclusion

Dans ce didacticiel, nous avons vu un aperçu rapide des collections Eclipse et des fonctionnalités qu'elles fournissent.

L'implémentation complète de ce tutoriel est disponibleover on GitHub.