chapitre 11 - Collections
Transcription
chapitre 11 - Collections
Chapitre 11 Collections (JDK 1.4) 1 Java Collections Framework: architecture d'interfaces, de classes abstraites et de classes concrètes permettant de stocker et manipuler efficacement des collections d'objets. Paquetage: java.util - Interfaces et classes abstraites - Classes concrètes - Algorithmes (tri, recherche binaire) - Arrays - Vues Modifications importantes avec le JDK 1.5 Ce chapitre décrit la situation avant le JDK 1.5 2 Structure générale: - Collection - Set - HashSet - SortedSet - TreeSet - List - ArrayList - LinkedList - Map - HashMap - SortedMap - TreeMap - On manipule des conteneurs d'objets (Object) Pas de limitation (théorique) sur la taille du conteneur 3 L'interface List - Collection - Set - HashSet - SortedSet - TreeSet - List – ArrayList – LinkedList spécifie les suites d'objets, avec les méthodes boolean add(Object o) int indexOf(Object o) Object get(int i) Object set(int i, Object o) ... 4 Deux implémentations concrètes de List: – – ArrayList: liste implémentée à l'aide d'un tableau redimensionnable dont on peut fixer la capacité initiale. – Efficace pour get,set, add (temps « constant amorti ») – Coûteux d'ajouter/supprimer un élément au début LinkedList: implémentation avec une liste doublement chainée – insertion/suppression d'un élément efficace – Accès séquentiel plus coûteux (temps linéaire) Exemple: Point p,p1,p2,p3; ... List l=new ArrayList(); l.add(p1); l.add(p2); l.add(p3); l.add(p2); for (int i=0;i<l.size();i++){ p=(Point) l.get(i); // get renvoie un Object p.affiche(); } ... 5 L'interface Set - Collection - Set - HashSet - SortedSet - TreeSet - List - ArrayList - LinkedList Set: ensembles au sens propre, sans duplication HashSet: implémentation avec table de hachage. Exemple: Point p,p1,p2,p3; ... Set s=new HashSet(); s.add(p1); s.add(p2); s.add(p3); s.add(p2); Iterator it=s.iterator(); while(it.hasNext()){ p=(Point) it.next(); p.affiche(); } // appelle affiche sur p1,p2,p3 (pas forcément dans cet ordre) ... 6 L'interface Collection (pas d'implémentation directe proposée) public interface Collection { // Basic Operations int size(); boolean isEmpty(); boolean contains(Object element); boolean add(Object element); // Optional boolean remove(Object element); // Optional Iterator iterator(); // Bulk Operations boolean containsAll(Collection c); boolean addAll(Collection c); // Optional boolean removeAll(Collection c); // Optional boolean retainAll(Collection c); // Optional void clear(); // Optional // Array Operations Object[] toArray(); Object[] toArray(Object a[]); } 7 Itérateurs objets permettant de parcourir une collection en faisant abstraction de l'implémentation. L'interface Collection propose une méthode Iterator iterator() qui renvoie à chaque invocation un nouvel objet itérateur sur la collection. Cet objet est manipulé via une référence de type Iterator: Interface Iterator: boolean hasNext() Returns true if the iteration has more elements. Object next() Returns the next element in the iteration. void remove() Removes from the underlying collection the last element returned by the iterator (optional operation). } 8 Exemple: Point p,p1,p2,p3; ... Collection c=new ArrayList(); l.add(p1); l.add(p2); l.add(p3); l.add(p2); ... Iterator it1=c.iterator(); p=(Point) it1.next(); // ref sur p1 ... p=(Point) it1.next(); // ref sur p2 ... p=(Point) it1.next(); // ref sur p3 it1.remove(); // élimine p3 de la liste ... Iterator it2=c.iterator(); while (it2.hasNext()){ p=(Point) it2.next(); p.affiche(); } ... 9 - - l'itérateur pointe "entre" deux éléments consécutifs, next() saute par-dessus l'élément suivant et le renvoie. remove() élimine l'élément traversé par le dernier next(). Attention: i.next(); i.next(); i.remove(); i.remove(); // impossible – – L'ordre de parcours dépend du type de collection: – séquentiel pour les listes – indéterminé pour HashSet – ordre naturel des éléments pour TreeSet Le comportement d'un itérateur est indéterminé si l'on essaie de modifier la collection autrement qu'avec remove. Exemple: implémentation de ListIterator dans LinkedList: levée d'une exception ConcurrentModificationException 10 Autre exemple: class Utilitaire{ ... public static void AfficheCollection(Collection c){ Iterator it=c.iterator(); while (it.hasNext()) System.out.println(it.next()); } ... } Remarque: on pourrait aussi concevoir une méthode public static void AfficheCollection(Iterator it) D'autres itérateurs: - itérateur bi-directionnel (interface ListIterator pour LinkedList) - on peut concevoir ses propres itérateurs, exemples: itérateurs "circulaires", ou filtrants (classes internes) Ancêtre d'Iterator: Interface Enumeration boolean hasMoreElements() Object nextElement(); 11 Comparaison d'objets Interface Comparable int compareTo(Object o) Compares this object with the specified object for order. Permet de définir une relation d'ordre totale entre les objets d'une classe. Si < relation d'ordre totale, alors a.compareTo(b) renvoie une valeur – strictement négative si a<b – 0 si a=b – strictement positive si a>b Quelques classes qui implémentent Comparable: Character, File, Long, Short, String, Float, Integer, Byte, Double, BigInteger, BigDecimal, Date... Relation d'ordre « naturelle », utilisée par défaut – par les méthodes de tri de tableaux/listes d'objets – par les collections ordonnées 12 Une méthode de la classe Arrays.java (du package java.util): private static void mergeSort(Object src[], Object dest[], int low, int high) { int length = high - low; // Insertion sort on smallest arrays if (length < 7) { for (int i=low; i<high; i++) for (int j=i; j>low && ((Comparable)dest[j-1]).compareTo((Comparable)dest[j])>0; j--) swap(dest, j, j-1); return; } // Recursively sort halves of dest into src int mid = (low + high)/2; mergeSort(dest, src, low, mid); mergeSort(dest, src, mid, high); // If list is already sorted, just copy from src to dest. This is an // optimization that results in faster sorts for nearly ordered lists. if (((Comparable)src[mid-1]).compareTo((Comparable)src[mid]) <= 0) { System.arraycopy(src, low, dest, low, length); return; } // Merge sorted halves (now in src) into dest for(int i = low, p = low, q = mid; i < high; i++) { if (q>=high || p<mid && ((Comparable)src[p]).compareTo(src[q]) <=0) dest[i] = src[p++]; else dest[i] = src[q++]; } } 13 Collections ordonnées SortedSet: sous-interface de Set pour les ensembles ordonnés Quelques méthodes: first() last() subset(Object initial,Object final) iterator() (parcourt l'ensemble dans l'ordre) L'ordre est soit l'ordre naturel, soit celui fourni à la construction par un objet Comparator (cf plus loin) Remarque: subset renvoie une vue adossée au Set TreeSet: implémentation de SortedSet avec un arbre équilibré. Parmi les constructeurs: TreeSet() Constructs a new, empty set, sorted according to the elements' natural order. TreeSet(Comparator c) Constructs a new, empty set, sorted according to the given comparator. 14 Exemple: import java.util.*; class TestSortedSet{ public static void main(String[] args){ SortedSet s=new TreeSet(); s.add("aaa"); s.add("ccc"); s.add("aaaa"); s.add("baaa"); s.add("aaab"); s.add("bbb"); for (Iterator it=s.iterator();it.hasNext();) System.out.println(it.next()); } } // affiche aaa,aaaa,aaab,baaa,bbb,ccc 15 Implémenter Comparable class Point implements Comparable{ ... public boolean equals(Object o){ if (this==o) return true; if (o==null) return false; if (getClass( ) != o.getClass( )) return false; Point p=(Point)o; return ((this.x==p.x)&&(this.y==p.y)); } public int compareTo(Object o){ if (!(o instanceof Point)) throw new ClassCastException(); Point q=(Point)o; if (this.equals(q)) return 0; if ((this.x<q.x)||((this.x==q.x)&&(this.y<q.y))) return -1; return 1; } 16 L'interface Comparator Si la solution précédente ne convient pas: Interface Comparator (java.util) int compare(Object o1, Object o2) Compares its two arguments for order. Exemple: – on déclare une classe PointComparator qui implémente Comparator et définit la relation d'ordre qui nous intéresse. – On récupère une référence c sur une instance de cette classe. – On passe c comme argument aux méthodes le permettant. Ces méthodes s'adresseront à c lorsqu'elles auront besoin d'effectuer des comparaisons de deux points. 17 Exemples: – Dans java.util.Collections: static void sort(List list) Sorts the specified list into ascending order, according to the natural ordering of its elements. static void sort(List list, Comparator c) Sorts the specified list according to the order induced by the specified comparator. – Dans les collections ordonnées: TreeSet() Constructs a new, empty set, sorted according to the elements' natural order. TreeSet(Comparator c) Constructs a new, empty set, sorted according to the given comparator. 18 Exemple: import java.util.*; class PointComparator implements Comparator{ public int compare(Object o1,Object o2){ if (!((o1 instanceof Point)&&(o2 instanceof Point))) throw new ClassCastException(); Point p1=(Point)o1; Point p2=(Point)o2; if (p1.equals(p2)) return 0; if ((p1.getY()<p2.getY())||((p1.getY()==p2.getY())&& (p1.getX()<p2.getX()))) return -1; return 1; } } // utiliser plutôt le pattern Singleton public class TestComparator{ public static void main(String[] args){ Comparator c=new PointComparator(); SortedSet s=new TreeSet(c); s.add(new Point(1,2)); s.add(new Point(0,3)); s.add(new Point(5,0)); for (Iterator it=s.iterator();it.hasNext();) System.out.println(it.next()); } } // l'ordre sera ici: (5,0),(1,2),(0,3) 19 L'interface Map - Map - HashMap - SortedMap – TreeMap Ne dérive pas de Collection. Map: « application » (table, tableau associatif) – une Map consiste en un ensemble de couples (clé,valeur) - chaque clé n'apparaît pas plus d'une fois (une valeur peut apparaître plusieurs fois) – utile pour trouver rapidement la valeur associée à une clé. Clés et valeurs sont des Object. Un couple (clé,valeur) est un Map.Entry Méthodes: Object put(Object key,Object value) renvoie l'objet précédemment associé à la clé ou null boolean containsKey(Object key) Object get(Object key) Object remove(Object key) supprime l'association de clé et renvoie l'objet associé ou null. 20 HashMap: implémente Map avec une table de hachage. – get, put en temps constant Exemple: stocker des couples (login,mot de passe) import java.util.*; class TestMap { public static void main(String[] args){ Map m=new HashMap(); m.put("user1","1234"); System.out.println(m.get("user1")); m.put("user2","medor"); m.put("user1","fifi"); System.out.println(m.containsKey("user2")); System.out.println(m.get("user1")); } } SortedMap: sous-interface de Map pour le cas où l'ensemble des clés est ordonné TreeMap: implémente SortedMap à l'aide d'arbres rouge/noir de sorte que les opérations containsKey, get, put, remove se font en temps O(log n) 21 Maps et Collections On peut obtenir des vues sur un objet Map Set keySet() renvoie l'ensemble des clés (sur lequel on peut ensuite itérer) Collection values() renvoie la collection des valeurs associées aux clés Set entrySet() renvoie l'ensemble des "entrées", i.e des couples (clé, valeur). Les « entrées » sont des instances d'une classe qui implémente l'interface Map.Entry Interface Map.Entry: Object getKey() Object getValue() Object setValue(Object value) 22 La classe Collections consiste uniquement en des methodes static qui agissent sur et renvoient des collections: Algorithmes: - min,max static Object min(Collection coll) static Object min(Collection coll, Comparator comp) - sort (tri fusion) - binarysearch (dans les listes ordonnées) - copy – shuffle Wrappers: méthodes qui renvoient des vues adossées à des collections: – vues synchronisées – vues immutables: static Collection unmodifiableCollection(Collection c) static List unmodifiableList(List list) static Map unmodifiableMap(Map m) static Set unmodifiableSet(Set s) static SortedMap unmodifiableSortedMap(SortedMap m) static SortedSet unmodifiableSortedSet(SortedSet s) 23 la classe Arrays Boîte à outils pour manipuler les tableaux. Méthodes (beaucoup de surcharges): – binarysearch – equals – fill – sort (quicksort) Exemples: static void sort(Object[] a) Sorts the specified array of objects into ascending order, according to the natural ordering of its elements. static void sort(Object[] a, Comparator c) Sorts the specified array of objects according to the order induced by the specified comparator. 24 Utiliser les classes de collections – – – – Les classes existantes remplacent souvent très avantageusement les tableaux. Les classes manipulent des collections d'Object. Conséquences: Pas de contrôle de type (penser notamment à equals, clone...) On doit donc souvent utiliser le transtypage Liste l=new ArrayList(); ... Point p=(Point) l.get(i); ... - Problème: les types primitifs ne sont pas des classes. 25 Classes enveloppes pour les types primitifs Classes qui permettent d'intégrer les types primitifs aux classes A chaque type primitif est associée une classe "enveloppe" dans java.lang: Integer, Double... Cette classe est immutable. Méthodes: - constructeur à un argument (du type associé) - emballage/déballage Exemple: int i=4; Integer envi=new Integer(i); int j=envi.intValue(); // emballage // déballage Types primitifs et collections: List l=new ArrayList(); l.add(new Integer(13)); ... int i=((Integer) l.get(0)).intValue(); JDK 1.5: emballage et déballage implicites 26 Compléments Concevoir ses propres classes de collections Utiliser les squelettes d'implémentation Dans l'architecture sont incluses des classes abstraites qui fournissent un squelette d'implémentation qui facilite la conception de nouvelles classes. (source: http://www.liafa.jussieu.fr/~carton/) 27 Exemple: public abstract class AbstractCollection extends Object implements Collection This class provides a skeletal implementation of the Collection interface, to minimize the effort required to implement this interface. To implement an unmodifiable collection, the programmer needs only to extend this class and provide implementations for the iterator and size methods. (The iterator returned by the iterator method must implement hasNext and next.) To implement a modifiable collection, the programmer must additionally override this class's add method (which otherwise throws an UnsupportedOperationException), and the iterator returned by the iterator method must additionally implement its remove method. The programmer should generally provide a void (no argument) and Collection constructor, as per the recommendation in the Collection interface specification. The documentation for each non-abstract methods in this class describes its implementation in detail. Each of these methods may be overridden if the collection being implemented admits a more efficient implementation. Il peut être nécessaire de redéfinir certaines des méthodes par souci d'optimisation. 28 Respecter le contrat des interfaces implémentées Exemple (Collection): « All general-purpose Collection implementation classes (which typically implement Collection indirectly through one of its subinterfaces) should provide two "standard" constructors: a void (no arguments) constructor, which creates an empty collection, and a constructor with a single argument of type Collection, which creates a new collection with the same elements as its argument. In effect, the latter constructor allows the user to copy any collection, producing an equivalent collection of the desired implementation type. There is no way to enforce this convention (as interfaces cannot contain constructors) but all of the general-purpose Collection implementations in the SDK comply. » Cas des classes immutables Pour simplifier l'architecture, les interfaces proposent plusieurs méthodes optionelles, dont les mutateurs Exemple (Collection): boolean add(Object o) Ensures that this collection contains the specified element (optional operation) Il faut donc implémenter ces méthodes en levant si nécessaire une exception UnsupportedOperationException (remarque: penser aux vues) 29
Documents pareils
•Collection Collection (conteneur) est un objet qui regroupe
Un itérateur permet de parcourir une collection
La notion d’itérateur est implantée en Java par l’interface Iterator
public boolean hasNext()
public Object next()
public void remove() (enlève le de...