On crée une classe paramétrée en plaçant le type inconnu
(dans l’exemple ci-dessous :
T
) entre chevrons
à côté du nom de la classe.
package collections.exemples; public class ClasseParametree<T> { private T data; public ClasseParametree(T data) { this.data = data; } public T get() { return data; } public void set(T data) { this.data = data; } public static void main(String[] args) { ClasseParametree<String> conteneurString = new ClasseParametree<>( "toto"); String chaine = conteneurString.get(); System.out.println(chaine); ClasseParametree<Integer> conteneurInt = new ClasseParametree<>(5); int entier = conteneurInt.get(); System.out.println(entier); } }
On peut voir une classe paramétrée comme un moule à classes.
On est amené naturellement à se demander si
ClasseParametree<String>
hérite de
ClasseParametree<Object>
. Un exercice traite cette
question...
Le mécanisme des classes paramétrées en Java en bien plus fin que les templates utilisées en C++. Les templates ne sont que de vulgaires rechercher/remplacer, alors qu’en Java, le code compilé est le même que si les types ne sont pas paramétrés. Les types paramétrés de java ne sont donc qu’un moyen pour le compilateur de s’assurer que vous faites les choses proprement en vous obligeant à déclarer les types que vous placez dans les collections.
Il est possible depuis une classe non paramétrée d’hériter d’une classe paramétrée en précisant son type :
package collections.exemples; public class StringWrapper implements Comparable<StringWrapper> { private String data; public StringWrapper(String data) { this.data = data; } public String getData() { return data; } public void setData(String data) { this.data = data; } @Override public int compareTo(StringWrapper autre) { return data.compareTo(autre.getData()); } public static void main(String[] args) { StringWrapper e1 = new StringWrapper("toto"), e2 = new StringWrapper("tutu"); System.out.println(e1.compareTo(e2)); } }
Il est souvent nécessaire que le type servant de paramètre vérifie
certaines propriétés. Si vous souhaitez par exemple que l’objet hérite
de
Comparable
, vous avez la possibilité de poser cette
contrainte avec le paramètre
<T extends Comparable<T>>
.
package collections.exemples; public class ComparableWrapper<T extends Comparable<T>> implements Comparable<ComparableWrapper<T>> { private T data; public ComparableWrapper(T data) { this.data = data; } public T getData() { return data; } public void setData(T data) { this.data = data; } @Override public int compareTo(ComparableWrapper<T> autre) { return data.compareTo(autre.getData()); } public static void main(String[] args) { ComparableWrapper<String> e1 = new ComparableWrapper<>("toto"), e2 = new ComparableWrapper<>("tutu"); System.out.println(e1.compareTo(e2)); ComparableWrapper<Integer> i1 = new ComparableWrapper<>(4), i2 = new ComparableWrapper<>(3); System.out.println(i1.compareTo(i2)); } }
La distribution officielle de Java est fournie avec plusieurs milliers
de classes. Les
Collections
sont des structures de données
permettant d’optimiser des opérations comme le tri, la recherche de
plus petit élément, etc. Les collections sont donc des regroupements
d’objets.
Set<T>
Un ensemble (
Set<T>
) est un regroupement d’éléments
de type
T
, non ordonnés et sans doublons.
package collections.exemples; import java.util.HashSet; import java.util.Set; public class SetInscriptions { public static void main(String[] args) { Set<String> inscrits = new HashSet<>(); inscrits.add("Lucien"); inscrits.add("Raymond"); inscrits.add("Huguette"); System.out.println(inscrits.contains("Gégé")); System.out.println(inscrits.contains("Raymond")); for (String nom : inscrits) System.out.println(nom); } }
SortedSet<T>
package collections.exemples; import java.util.SortedSet; import java.util.TreeSet; class Coordonnees implements Comparable<Coordonnees> { private int x, y; public Coordonnees(int x, int y) { this.x = x; this.y = y; } @Override public String toString() { return x + " " + y; } @Override public int compareTo(Coordonnees autre) { if (x == autre.x) return y - autre.y; return x - autre.x; } } public class SortedSetCoordonnees { public static void main(String[] args) { SortedSet<Coordonnees> cases = new TreeSet<>(); cases.add(new Coordonnees(1, 6)); cases.add(new Coordonnees(7, 3)); cases.add(new Coordonnees(-2, 5)); cases.add(new Coordonnees(1, 5)); for (Coordonnees c : cases) System.out.println(c); } }
package collections.exemples; import java.util.SortedSet; import java.util.TreeSet; public class SortedSetComparator { public static void main(String[] args) { SortedSet<String> dico = new TreeSet<> ( (str1, str2) -> str1.length() - str2.length() ); // ou bien /* SortedSet<String> dico = new TreeSet<>(new Comparator<String>() { @Override public int compare(String str1, String str2) { return str1.length() - str2.length(); } }); */ dico.add("xyz"); dico.add("abcde"); dico.add("mp"); dico.add("gfeadcba"); for (String s : dico) System.out.println(s); } }
Lists<T>
Une liste (
List<T>
) est un ensemble d’éléments de type
T
, disposés dans l’ordre dans lequel ils ont été insérés,
et contenant éventuellement des doublons.
package collections.exemples; import java.util.LinkedList; import java.util.List; public class ListPalmares { public static void main(String[] args) { List<String> palmares = new LinkedList<>(); palmares.add("Ginette"); palmares.add("Gertrude"); palmares.add("Maurice"); for (String nom : palmares) System.out.println(nom); } }
Maps<T>
Une application, (
Map<K, T>
) permet d’associer à des
clés de type
K
des objets de type
T
.
package collections.exemples; import java.util.HashMap; import java.util.Map; public class HashMapSalaires { public static void main(String[] args) { Map<String, Integer> salaires = new HashMap<>(); salaires.put("Raymond", 1000); salaires.put("Marcel", 2000); salaires.put("Ursule", 3000); for(String nom : salaires.keySet()) System.out.println("Le salaire de " + nom + " est " + salaires.get(nom) + " euros."); } }
package collections.exemples; import java.util.Map.Entry; import java.util.SortedMap; import java.util.TreeMap; public class SortedMapSalaires { public static void main(String[] args) { SortedMap<String, Integer> salaires = new TreeMap<>(); salaires.put("Dédé", 5000); salaires.put("Marcel", 2000); salaires.put("Ginette", 3000); salaires.put("Lucienne", 1000); for (String e : salaires.keySet()) System.out.println(e); for (int e : salaires.values()) System.out.println(e); for (Entry<String, Integer> e : salaires.entrySet()) System.out.println("Le salaire de " + e.getKey() + " est " + e.getValue()); } }
Iterable<T>
Il n’est possible d’utiliser la boucle
for
simplifiée que si
collection parcourue implémente
Iterable<T>
.
Voici un exemple de collection itérable :
package collections.exemples; import java.util.Iterator; public class IterableArray implements Iterable<Integer> { private final int TAILLE; private int[] tableau; public IterableArray(int taille) { this.TAILLE = taille; tableau = new int[taille]; } public void set(int i, int data) { tableau[i] = data; } public int get(int i) { return tableau[i]; } @Override public Iterator<Integer> iterator() { return new Iterator<Integer>() { private int index = -1; @Override public boolean hasNext() { index++; return index < TAILLE; } @Override public Integer next() { return get(index); } @Override public void remove() { for (int i = index; i < TAILLE - 1; i++) set(i, get(i + 1)); set(TAILLE - 1, 0); index --; } }; } public static void main(String[] args) { IterableArray tab = new IterableArray(10); for (int i = 0; i < 10; i++) tab.set(i, i + 1); Iterator<Integer> iterator = tab.iterator(); while (iterator.hasNext()) { int value = iterator.next(); if (value % 2 != 0) iterator.remove(); } for (int value : tab) System.out.println(value); } }