Programmierung

Ansicht oder Kopie?

Es lohnt sich oft, den Vertrag einer Methode zu lesen, also die Dokumentation, welche die Methode, ihre Argumente, ihre Rückgabe und die Auswirkung auf den Status des Objektes beschreibt. Bei manchen Methoden von Java-Collection-Klassen ist das besonders wichtig, denn sie liefern nicht unbedingt das, was der Name der Methode suggeriert. Z.B. gibt die Methode subList von java.util.List keine Teilkopie, sondern eine Ansicht der Instanz zurück, auf der sie aufgerufen wird. Die zurückgegebene Teilliste zeigt auf einen Teil der ursprüngliche Liste, der durch die angegebenen Indizes begrenzt wird, ist also keine Kopie. Welche Konsequenzen dies hat, veranschaulicht folgendes Beispiel, bei welchem auf eine Liste von Zeichenketten wie auf einen Stapel zugegriffen wird.

List<String> list = new LinkedList<String>();

public List<String> popItems( final int maxItems ) {
    // consider how many items are there
    int k = maxItems < list.size() ? maxItems : list.size();
    // (!!!) get the first k items (!!!)
    final List<String> subList = list.subList( 0, k );
    // remove retrieved items from the list
    list.removeAll( subList );
    // return the requested items
    return subList;
}

Die Ausführung des Codes führt zu einer Ausnahme: ConcurrentModificationException. Die ursprüngliche Liste darf nämlich nach dem Aufruf von subList, solange die Teilliste existiert (erreichbar ist), nicht strukturell verändert werden. Es dürfen dieser also keine Elemente weggenommen oder hinzugefügt werden. Strukturelle Änderungen sind nur über die erhaltene Ansicht möglich, weil diese sonst möglicherweise korrumpiert würde. Das obige Code-Schnipsel ist allerdings leicht zu reparieren, indem wir einfach den Geltungsbereich der Teilansicht begrenzen. Statt die Ansicht direkt zu verwenden, erzeugen wir mit dieser eine alleinstehende Kopie.

    // (!!!) make a copy of the first k items (!!!)
    final List<String> subList
        = new LinkedList<String>( list.subList( 0, k ) );

Ebenso ist übrigens auch eine Liste, die mit java.util.Arrays.asList erzeugt wurde, nur eine Ansicht des Feldes, das als Argument übergeben wurde. Die Komplementärmethode java.util.List.toArray dagegen erzeugt in jedem Fall ein neues Feld. Folgendes Code-Schnipsel ist demnach eine umständliche Art – wer sein Rahmenwerk kennt, benutzt dafür natürlich Arrays.copyOf – eine Kopie von einem Feld anzulegen.

    String[] stringArray = {"eins", "zwei", "drei"};
    // create a List view of the array
    List stringList = Arrays.asList( stringArray );
    // copy the list (and its backing array)
    String[] arrayCopy = (String[]) stringList.toArray();

Es ist ressourcenschonend, eine Ansicht einer Collection zu verwenden, manchmal jedoch ist es notwendig, eine Kopie anzulegen.

28. April 2011 von Kai Yves Linden
Kategorien: Programmierung | Schlagwörter: , | Kommentare deaktiviert für Ansicht oder Kopie?