Examen final - solution
1 Flots compressés
Partie 1
Le patron Decorator, qui nous permet de décorer un flot d'entrée quelconque pour lui ajouter la possibilité de décompresser un flot compressé.
Partie 2
public final class RLEInputStream extends InputStream { private InputStream stream; private int value = -1; private int count = 0; public RLEInputStream(InputStream stream) { this.stream = stream; } @Override public int read() throws IOException { if (count-- > 0) { return value; } else { count = stream.read(); if (count == -1) return -1; // end of stream reached value = stream.read(); if (value == -1) throw new IOException("malformed RLE stream: " + "no value found for count " + count); return value; } } @Override public void close() throws IOException { stream.close(); } }
2 Itérateurs
Partie 1
Il s'agit du patron Composite. On le voit au fait que AddingIterator
est lui-aussi un itérateur et qu'il compose le comportment de deux autres itérateurs.
Partie 2
Oui, il est possible et même facile de construire l'itérateur iSum3
, de la manière suivante :
Iterator<Integer> iSum3 = new AddingIterator(iSum, i3);
Partie 3
10, 11, 12.
Partie 4
public final class AddingIterator implements Iterator<Integer> { private final Iterator<Integer> i1, i2; public AddingIterator(Iterator<Integer> i1, Iterator<Integer> i2) { this.i1 = i1; this.i2 = i2; } @Override public boolean hasNext() { return i1.hasNext() && i2.hasNext(); } @Override public Integer next() { return i1.next() + i2.next(); } @Override public void remove() { throw new UnsupportedOperationException(); } }
Partie 5
On pourrait utiliser le patron Strategy pour représenter l'opération de combinaison au moyen d'un objet implémentant une interface dotée d'une seule méthode, la méthode de combinaison.
3 Vecteurs creux
Partie 1
Il faut bien penser à copier la table nonZeroEntries
reçue en argument, faute de quoi la classe SparseVector
n'est pas immutable.
public SparseVector(Map<Integer, Double> nonZeroEntries, int size){ if (size < 0) throw new IllegalArgumentException("invalid size: " + size + " (must be >= 0)"); for (int index: nonZeroEntries.keySet()) { if (! (0 <= index && index < size)) throw new IllegalArgumentException("invalid index: " + index +" (must be in [0;" + (size - 1) +"]"); } this.nonZeroEntries = new HashMap<>(nonZeroEntries); this.size = size; }
Partie 2
public int size() { return size; }
Partie 3
public double get(int index) { if (! (0 <= index && index < size)) throw new IllegalArgumentException("invalid index: " + index +" (must be in [0;" + (size - 1) +"]"); Double maybeEntry = nonZeroEntries.get(index); return maybeEntry == null ? 0 : maybeEntry; }
Il est également possible d'utiliser containsKey
pour vérifier la présence de l'élément d'index donné dans la table des éléments non nuls, plutôt que de tirer parti du fait que get
retourne null
dans ce cas, comme c'est fait ici.