Mise au point d`une méthode efficace de tri d`un vecteur en Java.

Mise au point d’une m´ethode efficace de tri
d’un vecteur en Java.
S´
ebastien Pi´
erard
8 juin 2007
Dans cet article, nous pr´esentons une m´ethode efficace pour trier le con-
tenu d’un vecteur, instance de la classe java.util.Vector. Typiquement, le
programmeur utilisera cette structure de donn´ees comme une liste, telle
que d´efinie par l’interface java.util.List. Il lui est ainsi possible d’appeler
la m´ethode statique sort de la classe java.util.Collections. Ce n’est malheu-
reusement pas la bonne fa¸con de proc´eder.
Commen¸cons par rappeler ce qu’est un vecteur. Il s’agit d’une structure
de donn´ees dont l’acc`es index´e se fait en temps constant, mais dont le nombre
d’´el´ements peut varier. Son impl´ementation est r´ealis´ee grˆace `a un tableau
surdimensionn´e, permettant ainsi l’ajout de nouveaux ´el´ements. Lorsque la
taille du tableau devient insuffisante, un nouveau tableau est allou´e et les
r´ef´erences vers les objets contenus sont copi´ees depuis l’ancien tableau dans
le nouveau. La classe Vector contient notamment les deux champs suivants :
/**
* The array buffer into which the components of the vector are stored.
* Any array elements following the last element in the Vector are null.
*/
protected Object[] elementData ;
/**
* The number of valid components in this Vector object. Components
* elementData[0] through elementData[elementCount-1] are the actual items.
*/
protected int elementCount ;
1
Voyons `a pr´esent pourquoi l’utilisation de Collections.sort est inefficace.
Pour cela, observons le code-source du projet GNU Classpath 0.95 1.
Dans java.util.Collections :
2107: public static <T> void sort(List<T> l, Comparator<? super T> c)
2108: {
2109: T[] a = (T[]) l.toArray();
2110: Arrays.sort(a, c);
2111: ListIterator<T> i = l.listIterator();
2112: for (int pos = 0, alen = a.length; pos < alen; pos++)
2113: {
2114: i.next();
2115: i.set(a[pos]);
2116: }
2117: }
Dans java.util.Vector :
179: public synchronized void copyInto(Object[] a)
180: {
181: System.arraycopy(elementData, 0, a, 0, elementCount);
182: }
550: public synchronized Object[] toArray()
551: {
552: Object[] newArray = new Object[elementCount];
553: copyInto(newArray);
554: return newArray;
555: }
Autrement dit, la m´ethode na¨ıve a deux sources d’inefficacit´e. Premi`ere-
ment, elle n´ecessite de recopier le tableau interne du vecteur. Cela est n´eces-
saire car la m´ethode propos´ee pour trier est g´en´erale, et ne peut donc pas
tirer parti du fait qu’un vecteur utilise un tableau en interne. Deuxi`emement,
le parcours de la structure pour y replacer les ´el´ements tri´es est lourde de
par les nombreux appels de fonctions n´ecessaires.
La m´ethode de tri mise au point tire parti du fait que la classe Vector
n’est pas d´eclar´ee finale, et que le tableau interne est seulement protected.
Nous cr´eons donc une nouvelle classe, SortableVector, qui h´erite de Vector
et y ajoute les fonctions de tri. Nous pouvons ainsi passer le tableau interne
directement `a Arrays.sort. De plus, cette fa¸con de proeder permet d’ajouter
des fonctions permettant de trier une partie du contenu du vecteur, ce qui
n’est pas possible via la classe Collections. Voici la solution propos´ee :
1http ://developer.classpath.org/doc/
2
import java.util.Arrays ;
import java.util.Collection ;
import java.util.Comparator ;
import java.util.Vector ;
public class SortableVector <E> extends Vector <E> {
public SortableVector () {
super () ;
}
public SortableVector ( Collection <? extends E> c ) {
super ( c ) ;
}
public SortableVector ( int initialCapacity ) {
super ( initialCapacity ) ;
}
public SortableVector ( int initialCapacity , int capacityIncrement ) {
super ( initialCapacity , capacityIncrement ) ;
}
public void sort () {
Arrays.sort ( elementData , 0 , elementCount ) ;
}
public void sort ( Comparator <? super E> c ) {
Arrays.<E>sort ( ( E [] ) elementData , 0 , elementCount , c ) ;
}
public void sort ( int fromIndex , int toIndex ) {
checkIndex ( fromIndex ) ;
checkIndex ( toIndex ) ;
Arrays.sort ( elementData , fromIndex , toIndex ) ;
}
public void sort ( int fromIndex , int toIndex , Comparator <? super E> c ) {
checkIndex ( fromIndex ) ;
checkIndex ( toIndex ) ;
Arrays.<E>sort ( ( E [] ) elementData , fromIndex , toIndex , c ) ;
}
private void checkIndex ( int index ) {
if ( index < 0 || index >= elementCount )
throw new ArrayIndexOutOfBoundsException () ;
}
}
3
Il convient `a pr´esent de mesurer le temps requis pour effectuer un tri, et
ce pour diverses quantit´es de donn´ees. Pour ce faire, nous mesurons le temps
n´ecessaire `a la cr´eation, au remplissage et au tri des structures de donn´ees.
Nous moyennons ces temps sur une vingtaine de mesures. Nous r´ep´etons en-
suite la proc´edure en d´esactivant la commande de tri, pour avoir le temps
r´eellement consomm´e par la fonction de tri. Le graphique suivant illustre les
r´esultats obtenus.
0 1 2 3 4 5 6 7 8 9 10
x 105
0
500
1000
1500
2000
2500
3000
nombre d’elements a trier
temps ( millisecondes )
avec SortableVector
avec Collections.sort
avec Collections.sort sans toArray ()
Nous en concluons que la m´ethode d´ecrite est de loin pr´ef´erable `a l’utili-
sation de la m´ethode disponible. Il est ainsi possible de gagner jusqu’`a 40%
du temps d’ex´ecution. Sur le graphique, nous avons ´egalement repr´esene
en noir le temps requis par Collections.sort auquel on a soustrait le temps
n´ecessaire `a toArray (). On peut ainsi identifier plus pr´esis´ement la source
d’inefficacit´e de Collections.sort : elle ne vient qu’en faible partie du reco-
piage du tableau, sa source principale ´etant la fa¸con de replacer les ´el´ements
tri´es dans la structure de donn´ees.
L’inconenient principal de la m´ethode propos´ee est l’obligation `a utiliser
la classe SortableVector. Ainsi, il est impossible de trier les ´el´ements d’une
structure d´eclar´ee comme Vector ou toute sous classe autre que SortableVec-
tor, par exemple Stack. Une solution alternative serait de d´efinir Sortable-
Vector dans le package java.util et de transformer les m´ethodes pour qu’elles
prennent en argument le vecteur sur lequel agir.
Enfin, notons que l’impl´ementation de java.util.ArrayList est similaire,
du moins dans le projet GNU Classpath. Cependant, les champs utiles ´etant
d´eclar´es priv´es, il n’y a pas moyen de s’en servir.
4
1 / 4 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !