Collections

Pour une référence complète, voir Java 8 Lambdas, par Richard Warburton (O’Reilly) ou le tutorial Oracle.

Collection = plusieurs choses regroupées, dont le regroupement peut être manipulé comme un tout.

Les collections définissent 2 structures de base :
- Une Collection est un regroupement d'objets.
- Une Map est un groupement d'associations (= dictionnaire, tableau associatif). Collections Collections Lorsqu'on choisit une implémentation de Collection pour travailler, prendre en compte les performances, suivant les cas d'utilisation.
Par ex, LinkedList a de très bonnes preformances pour l'ajout / suppression d'éléments, mais pas pour du random access.
Voir la marker interface java.util.RandomAccess :
List<?> l = ...;
if(!(l instanceof RandomAccess)) l = new ArrayList<?>(l);
ArrayList est une implémentation très souvent utilsée.

Vector n'est là que pour des raisons de compatibilité ascendante, utiliser ArrayList à la place.
Stack n'est là que pour des raisons de compatibilité ascendante, utiliser Deque à la place.

Deux classes contenant des utilitaires (méthodes statiques) souvent utilisés :
- java.util.Collections
- java.util.Arrays
Voir aussi java.lang.System.arraycopy(), java.lang.Class.isArray()

L'interface collection

Définit les méthodes communes à toutes les implémentations, voir l'apidoc de java.util.Collection.
Collection<E>, paramétrée par le type d'éléments qu'elle contient.

Quelques exemples d'utilisation :
// création "normale"
Collection<String> c1 = new ArrayList<>();

// création à partir de méthodes utilitaires
Collection<String> c2 = Arrays.asList("toto", "titi");

// La plupart des implémentations ont un constructeur par recopie
Collection<String> c3 = new ArrayList<String>(c2);

// Ajout
c2.add("tata"); // Ajout d'un élément
c3.addAll(c2); // Ajout de tous les éléments d'une autre collection

// Suppression
c2.remove("toto"); // Supprime un seul élément
c2.removeAll(c3); // Supprime une collection d'élément
c2.retainAll(c3); // Supprime tous les éléments qui ne sont pas dans c3
c.clear(); // RAZ, supprime tous les éléments d'une collection

// Accès aux éléments
c2.get(1);

// Taille d'une collection
boolean b = c1.isEmpty(); // c is now empty, so true
int s = c1.size();

// La plupart des implementations de Collection ont redéfini toString()
System.out.println(c1);

// Conversion vers un tableau.
Object[] elements = c.toArray();
String[] strings = c.toArray(new String[c.size()]);
(code dans Demo1.java) Toutes ces opérations sont utilisables avec n'importe quelle implémentation des sous-interfaces de Collection (Set, List ou Queue).

Itération

Itération classique

Boucle for ou foreach :
List<String> c = new ArrayList<String>();
for(String word : c) {
    System.out.println(word);
}
for( declaration : expression )
    statement

Iterator

expression doit être un tableau, ou une classe implémentant java.lang.Iterable.
public interface Iterable<E> {
    java.util.Iterator<E> iterator();
}
Dans une boucle classique, l'itérateur sous-jacent est invisible.

on peut explicitement utiliser l'itérateur d'une collection car java.util.Collection définit une méthode :
public Iterator<E> iterator()
Une boucle classique équivaut à :
List<String> c = new ArrayList<String>();
for(Iterator<String> i = c.iterator(); i.hasNext();) {
    System.out.println(i.next());
}
Utilisable aussi avec while :
Iterator<String> iterator() = c.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}
Interface java.util.Iterator :
public interface Iterator<E> {
    boolean hasNext();
    E next();
    void remove(); 
}
Attention, next() fait 2 choses : renvoie l'élément courant de l'itération ET avance dans la collection.

Iterator est paramétré par le type de la collection qu'elle traverse :
Il faut un Iterator<String> pour parcourir une Collection<String>.

Maps

Une map est une collection contenant des associations clé, valeur ; parfois appelé dictionnaire ou tableau associatif.

Exemples d'utilisation :
import java.util.*;

class Personne{
    private String nom;
    public Personne(String nom) { this.nom = nom; }
    @Override public String toString() { return nom; }
}

public class MapTest{
    
    public static void main(String[] args) {
        
        // création de la map
        
        Map<String, Personne> map = new HashMap<>();
        map.put("p1", new Personne("Personne 1"));
        map.put("p2", new Personne("Personne 2"));
        map.put("p3", new Personne("Personne 3"));
        
        // Affichage
        
        System.out.println("=== Utilisation de values() ===");
        for(Personne p : map.values()) {
            System.out.println(p); // n'affiche que les valeurs
        }
        
        System.out.println("=== Utilisation de keySet() ===");
        for(String key : map.keySet()) {
            System.out.println(key + " : " + map.get(key));
        }
        
        System.out.println("=== Utilisation de entrySet() ===");
        for(Map.Entry<String, Personne> entry : map.entrySet()) {
            System.out.println(entry.getKey() + " : " + entry.getValue());
        }
        
        System.out.println("=== Utilisation de iterator() ===");
        Iterator<Map.Entry<String, Personne>> entries = map.entrySet().iterator();
        while(entries.hasNext()) {
            Map.Entry<String, Personne> entry = entries.next();
            System.out.println(entry.getKey() + " : " + entry.getValue());
        }
        
        System.out.println("=== Utilisation de stream() ===");
        map.forEach((k,v)->System.out.println(k + "  :  " + v));
    }
}