précédent | suivant | table des matières
|
La classe abstraite AbstractList implémente certaines des nouvelles fonctionnalités de l’interface List. Ces nouvelles fonctionnalités sont des méthodes avec indice. Elles supposent que la structure sous-jacente servant à représenter la liste est une structure à accès direct par indice (tableau). Pour implanter un conteneur avec une liste chaînée, on utilisera plutôt la classe abstraite AbstractSequentialList
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>
1 Les méthodes abstraites :
abstract public E get(int index);
2 Les méthodes optionnelles (à définir dans les sous-classes qui le souhaitent):
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E set(int index, E element) { throw new UnsupportedOperationException(); }
public E remove(int index) { throw new UnsupportedOperationException(); }
3 Les autres méthodes :
public boolean add(E o) { add(size(), o); return true; }Les méthodes indexOf :
public int indexOf(Object o) { ListIterator<E> e = listIterator(); if (o==null) { while (e.hasNext()) if (e.next()==null) return e.previousIndex(); } else { while (e.hasNext()) if (o.equals(e.next())) return e.previousIndex(); } return -1; }
public int lastIndexOf(Object o) { ListIterator<E> e = listIterator(size()); if (o==null) { while (e.hasPrevious()) if (e.previous()==null) return e.nextIndex(); } else { while (e.hasPrevious()) if (o.equals(e.previous())) return e.nextIndex(); } return -1; }Les opérations ensemblistes :
public void clear() { for (Iterator<E> it = Iterator(); it.hasNext(); ){ it.next(); it.remove(); } }
public boolean addAll(int ind, Collection<? extends E> c) { boolean modifie = false; Iterator<? extends E> e = c.iterator(); while (e.hasNext()) { add(index++, e.next()); modifie = true; } return modifie; }
4 Implémentation des itérateurs :
public Iterator<E> iterator() { return Itr(); }
La classe imbriquée Itr implémente l’interface Iterator, et est définie de la façon suivante :
private class Itr implements Iterator { // indice du prochain élément à retourner par next int curseur =0; // indice du dernier élément retourné par next int derRet = -1;
modCompte est un attribut de la classe AbstractList qui représente le nombre de fois que la liste a été structurellement modifiée : une modification structurelle est un (ou plusieurs) ajout(s), un (ou plusieurs) retrait(s) qui risquent de rendre incohérents les parcours à l'aide d'itérateurs. Un itérateur stocke la valeur de modCompte quand il est créé, et lève une exception si, lors d'une utilisation de l'itérateur, le modCompte de l'objet collection ne correspond pas au modCompte de l'itérateur.
intmodCompteAttendu = modCompte; public boolean hasNext() { return curseur != size(); }
public E next() { testModification(); try { E next = get(curseur); derRet = curseur++; return next; } catch(IndexOutOfBoundsException e) { testModification(); throw new NoSuchElementException(); } } |
final void testModification() { if (modCompte != modCompteAttendu) throw new ConcurrentModificationException(); } |
public void remove() { if (derRet == -1) // l'opération précédente n'est pas un next throw new IllegalStateException(); testModification(); try { AbstractList.this.remove(derRet);// appel du remove de la classe englobante if(derRet < curseur) curseur--; derRet = -1; modCompteAttendu= modCompte; // on remet à jour modCompteAttendu : modCompte a été modifié. } catch(IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } }
Les méthodes suivantes retournent un ListIterator :
ListIterator listIterator() { return listIterator(0); }
ListIterator listIterator(final int index) {
if (index<0 || index>nbElements)
throw new IndexOutOfBoundsException("Index: "+index);
return new ListItr(index);
}
La classe imbriquée ListItr implémente l’interface ListIterator :
private class ListItr extends Itr implements ListIterator<E>
ListItr(int index) { curseur = index; }
public boolean hasPrevious() { return curseur != 0; }
public E previous() { testModification(); try { int i = curseur - 1; E previous = get(i); derRet = curseur = i; return previous; } catch(IndexOutOfBoundsException e) { testModification(); throw new NoSuchElementException(); } }
public int nextIndex() { return curseur; }
public int previousIndex() { return curseur-1; }
void set(Object o) { if (derRet == -1) throw new IllegalStateException(); testModification(); try{ AbstractList.this.set(derRet, o); modCompteAttendu= modCompte; }catch(IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } }
public void add(Object o) { testModification(); try { AbstractList.this.add(curseur++, o); derRet = -1; modCompteAttendu= modCompte; }catch(IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } }
5 La méthode subList( int depuis, int jusqua)
public List<E> subList(int fromIndex, int toIndex) { return (this instanceof RandomAccess ) new RandomAccessSubList<E>(this, fromIndex, toIndex) : new SubList<E>(this, fromIndex, toIndex)); }
Les classes SubList (sous classe de AbstractList) et sa dérivée RandomAccessSubList sont des classes privées du paquetage java.util.
6 La méthode equals
La méthode equals est définie de la façon suivante :
public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof List)) return false; ListIterator<E> e1 = listIterator(); ListIterator e2 = ((List) o).listIterator(); while(e1.hasNext() && e2.hasNext()) { E o1 = e1.next(); Object o2 = e2.next(); if (!(o1==null ? o2==null : o1.equals(o2))) return false; } return !(e1.hasNext() || e2.hasNext()); }