Collection immuable ou non modifiable

De la Collections Cadre de Présentation :

Collections qui ne supportent pas les opérations de modification (telles que add , remove et clear ) sont appelées non modifiable . Les Collections qui ne sont pas impossibles à modifier sont modifiable .

Collections qui garantissent en outre qu'aucun changement dans l'objet Collection seront visibles sont appelés immuable . Les Collections qui ne sont pas immuables sont mutable .

Je ne peux pas comprendre la distinction.

Quelle est la différence entre inmodifiable et immuable ici?

137
demandé sur TylerH 2012-01-17 13:39:19

6 réponses

une collection non modifiable est souvent un emballage autour d'une collection modifiable dont un autre code peut encore avoir accès à . Donc, alors que vous ne peut pas y apporter de modifications si vous avez seulement une référence à la collection non modifiable, vous ne pouvez pas compter sur le contenu ne changeant pas.

An immuable collection garantit que rien peut changer la collection plus. S'il enveloppe une collection modifiable, il s'assure qu'aucun autre code n'a accès à cette collection modifiable. Notez que bien qu'aucun code ne puisse changer quels objets la collection contient des références, les objets eux - mêmes peuvent encore être mutables-la création d'une collection immuable de StringBuilder ne "gèle" pas d'une manière ou d'une autre ces objets.

fondamentalement, la différence est de savoir si un autre code peut être en mesure de changer la collection derrière votre dos.

175
répondu Jon Skeet 2012-01-17 09:48:57

essentiellement unModifiable Collection est une vue, donc indirectement il pourrait encore être "modifié" d'une autre référence qui est modifiable. Aussi comme son juste un readonly view d'annother collection, lorsque la collection source change Collection non modifiable sera toujours présente avec les valeurs les plus récentes.

cependant immutable Collection peut être traitée comme une readonly copy d'une autre collection et ne peut pas être modifié. Dans ce cas , lorsque la collection source change, la Collection immuable ne reflète pas les changements

voici un cas de test pour visualiser cette différence.

@Test
public void testList() {

    List<String> modifiableList = new ArrayList<String>();
    modifiableList.add("a");

    System.out.println("modifiableList:"+modifiableList);
    System.out.println("--");


    //unModifiableList

    assertEquals(1, modifiableList.size());

    List<String> unModifiableList=Collections.unmodifiableList(
                                        modifiableList);

    modifiableList.add("b");

    boolean exceptionThrown=false;
    try {
        unModifiableList.add("b");
        fail("add supported for unModifiableList!!");
    } catch (UnsupportedOperationException e) {
        exceptionThrown=true;
        System.out.println("unModifiableList.add() not supported");
    }
    assertTrue(exceptionThrown);

    System.out.println("modifiableList:"+modifiableList);
    System.out.println("unModifiableList:"+unModifiableList);

    assertEquals(2, modifiableList.size());
    assertEquals(2, unModifiableList.size());
            System.out.println("--");



            //immutableList


    List<String> immutableList=Collections.unmodifiableList(
                            new ArrayList<String>(modifiableList));

    modifiableList.add("c");

    exceptionThrown=false;
    try {
        immutableList.add("c");
        fail("add supported for immutableList!!");
    } catch (UnsupportedOperationException e) {
        exceptionThrown=true;
        System.out.println("immutableList.add() not supported");
    }
    assertTrue(exceptionThrown);


    System.out.println("modifiableList:"+modifiableList);
    System.out.println("unModifiableList:"+unModifiableList);
    System.out.println("immutableList:"+immutableList);
    System.out.println("--");

    assertEquals(3, modifiableList.size());
    assertEquals(3, unModifiableList.size());
    assertEquals(2, immutableList.size());

}

Sortie

modifiableList:[a]
--
unModifiableList.add() not supported
modifiableList:[a, b]
unModifiableList:[a, b]
--
immutableList.add() not supported
modifiableList:[a, b, c]
unModifiableList:[a, b, c]
immutableList:[a, b]
--
74
répondu Prashant Bhate 2013-09-26 08:30:00

je pense que la principale différence est que le propriétaire d'une collection mutable pourrait vouloir fournir l'accès à la collection à un autre code, mais fournir cet accès par une interface qui ne permet pas à l'autre code de modifier la collection (tout en réservant cette capacité au Code propriétaire). Donc la collection n'est pas immuable, mais certains utilisateurs ne sont pas autorisés à changer la collection.

Oracle Java Collection wrapper tutorial a ceci à dire (italique ajouté):

Inmodifiable wrappers ont deux utilisations principales, comme suit:

  • pour rendre une collection immuable une fois qu'elle a été construite. Dans ce cas, c'est une bonne pratique de ne pas conserver une référence au Support collection. Cela garantit absolument l'immutabilité.
  • pour permettre à certains clients d'accéder en lecture seule à vos structures de données. Vous gardez une référence à la collection de supports mais à la main une référence à l'emballage. De cette façon, les clients peuvent regarder mais pas modifier, pendant que vous maintenez l'accès complet .
10
répondu Michael Burr 2012-01-17 09:50:31

si nous parlons de JDK Unmodifiable* vs guava Immutable* , en fait la différence est aussi dans performance . Les collections immuables peuvent être à la fois plus rapides et plus économes en mémoire si elles sont des enveloppes et non autour des collections régulières (les implémentations JDK sont des enveloppes). citant l'équipe de goyave :

le JDK fournit des Collections.méthodes non modifiablesxxx, mais à notre avis, ceux - ci peuvent être

<...>

  • inefficace: les structures de données ont encore tous les frais généraux des collections mutables, y compris les vérifications de modification simultanées, l'espace supplémentaire dans les tables de hachage, etc.
2
répondu Dmide 2015-03-25 21:26:02

pour citer java docs, à la différence des emballages de synchronisation, qui ajoutent des fonctionnalités à la collection enveloppée, les emballages non modifiables enlèvent des fonctionnalités. En particulier, ils suppriment la possibilité de modifier la collecte en interceptant toutes les opérations qui modifieraient la collecte et en lançant un UnsupportedOperationException .

Inmodifiable wrappers ont deux utilisations principales, comme suit:

pour faire un collection immuable une fois qu'il a été construit. Dans ce cas, c'est une bonne pratique de ne pas conserver une référence à la collection de supports. Cela garantit absolument l'immutabilité.

pour permettre à certains clients d'accéder en lecture seule à vos structures de données. Vous gardez une référence à la collection de supports, mais donnez une référence à l'emballage. De cette façon, les clients peuvent regarder mais pas modifier, pendant que vous maintenez un accès complet.

cela résume vraiment tout.

2
répondu Bharath 2015-07-23 20:41:32

comme indiqué ci-dessus non modifiable n'est pas comme immuable parce qu'une collection non modifiable peut être modifiée si par exemple une collection non modifiable a une collection déléguée sous-jacente qui est référencée par un autre objet et que l'objet la modifie.

en ce qui concerne immuable, il n'est même pas bien défini. Cependant, en général, cela signifie que l'objet "ne changera pas", mais qui devront être définies de manière récursive. Par exemple, je peux définir immuable sur les classes dont les variables d'instance sont toutes des primitives et dont les méthodes ne contiennent pas d'arguments et retournent des primitives. Les méthodes permettent ensuite récursivement aux variables d'instance d'être immuables et toutes les méthodes de contenir des arguments qui sont immuables et qui renvoient des valeurs immuables. Les méthodes devraient être garanties pour retourner la même valeur au fil du temps.

en supposant que nous pouvons faire cela, il ya aussi le concept thread safe. et vous pourriez être amenés à croire que immuable (ou non modifiable au fil du temps) implique également un thread sûr. Cependant ce n'est pas le cas et qui est le principal point que je fais ici, n'a pas encore été mentionné dans d'autres réponses. Je peux construire un objet immuable qui renvoie toujours les mêmes résultats mais n'est pas thread-safe. Pour voir cette hypothèse que je construis une collection immuable en maintenant les ajouts et les suppressions au fil du temps. Maintenant la collection immuable retourne ses éléments en regardant la collection interne (qui peut changer au fil du temps) puis (à l'interne) l'ajout et la suppression des éléments ajoutés ou supprimés après la création de la collection. De toute évidence, bien que la collection retournerait toujours les mêmes éléments, il n'est pas sûr de thread simplement parce qu'il ne changera jamais la valeur.

maintenant nous pouvons définir immuable comme des objets qui sont thread safe et ne changeront jamais. Il existe des lignes directrices pour créer des classes immuables qui conduisent généralement à ces classes, cependant, garder à l'esprit qu'il peut y avoir des moyens de créer des classes immuables, qui exigent une attention à la sécurité du fil, par exemple, comme décrit dans l'exemple de collection "snapshot" ci-dessus.

1
répondu dan b 2014-12-22 22:40:28