Collections (JDK 1.4)

powersmoneySoftware and s/w Development

Jul 14, 2012 (5 years and 1 month ago)

409 views

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 Collection
s
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);
// emballage
int j=envi.intValue();
// 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