216 votes

Collection immuable ou non modifiable

De la Aperçu du cadre des collections :

Les collections qui ne supportent pas les opérations de modification (comme les add , remove et clear ) sont désignés comme non modifiable . Les collections qui ne sont pas non modifiables sont modifiable .

Collections qui garantissent en outre qu'aucune modification de la Collection seront visibles sont appelées immuable . Les collections qui ne sont pas immuables sont mutable .

Je ne comprends pas la distinction.
Quelle est la différence entre non modifiable et immuable ici ?

250voto

Jon Skeet Points 692016

Une collection non modifiable est souvent une enveloppe autour d'une collection modifiable. à laquelle d'autres codes peuvent encore avoir accès . Alors que vous ne peut pas y apporter de modifications si vous ne disposez que d'une référence à la collection non modifiable, vous ne pouvez pas compter sur le fait que le contenu ne change pas.

Un site immuable garantit que rien ne peut plus changer la collection. S'il enveloppe une collection modifiable, il s'assure qu'aucun autre code n'a accès à cette collection modifiable. Notez que même si aucun code ne peut modifier les objets auxquels la collection fait référence, les objets eux-mêmes peuvent toujours être modifiables - créer une collection immuable de StringBuilder ne "gèle" pas en quelque sorte ces objets.

Fondamentalement, la différence porte sur la question de savoir si un autre code peut être en mesure de modifier la collection dans votre dos.

78 votes

Une collection immuable ne garantit pas que rien ne peut plus changer. Elle s'assure simplement que la collection elle-même ne peut pas être modifiée (et pas par enveloppement, mais par copie). Les objets qui sont présents dans la collection peuvent toujours être modifiés, et aucune garantie n'est donnée sur ceux-ci.

8 votes

@HieryNomus : Notez que je n'ai pas dit que rien ne pouvait changer - j'ai dit que rien ne pouvait changer la collection.

1 votes

Ok, j'ai peut-être mal lu ;) Mais c'est bien de le clarifier quand même.

125voto

Prashant Bhate Points 4669

En gros, unModifiable La collection est une vue, donc indirectement elle pourrait toujours être "modifiée" à partir d'une autre référence qui est modifiable. De plus, comme il s'agit simplement d'une vue en lecture seule d'une autre collection, lorsque la collection source change, la collection non modifiable sera toujours présente avec les dernières valeurs.

Cependant immutable La collection peut être traitée comme un copie en lecture seule d'une autre collection et ne peut être modifié. Dans ce cas, lorsque la collection source change, la collection immuable ne reflète pas les changements.

Voici un cas d'essai 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]
--

0 votes

Je ne vois pas de différence. Pouvez-vous m'expliquer en quoi Immutable est différent ? Je vois que Immutable et Unmodifiable génèrent des erreurs et que Add n'est pas pris en charge. Est-ce que quelque chose m'échappe ?

4 votes

@AKS Veuillez voir la sortie des trois dernières entrées de la liste après l'ajout de 'c' à la liste alors que les deux tailles de 'c' et de 'c' sont identiques. modifiableList et unModifiableList a augmenté immutableList la taille n'a pas changé

1 votes

Oh ! je l'ai eu ! :).. Donc ici vous avez modifié unmodifableList en utilisant les changements dans modifiableList, mais ImmutableList ne peut pas être modifié. Mais de la même façon vous pouvez modifier ImmutableList aussi, je pense qu'ici le client aura accès à la référence d'ImmutableList seulement, la référence à modifiableList, en utilisant laquelle ImmutableList est créée, ne sera pas exposée au client. n'est-ce pas ?

15voto

Michael Burr Points 181287

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

Oracle Tutoriel sur les collecteurs Java a ceci à dire (c'est nous qui soulignons) :

Les wrappers non modifiables ont deux utilisations principales, comme suit :

  • Pour rendre une collection immuable une fois qu'elle a été construite. Dans ce cas, il est bon de ne pas maintenir une référence à la collection de backing de soutien. 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 sauvegarde mais vous remettez une référence à l'enveloppe. De cette façon, les clients peuvent regarder mais pas modifier, tandis que vous conservez un accès complet .

6voto

user3234777 Points 113
    // normal list
    List list1 = new ArrayList();
    list1.add(1);

    // unmodifiable list
    List list2 = Collections.unmodifiableList(list1);

    // immutable list
    List list3 = Collections.unmodifiableList(new ArrayList<>(list1));

    list1.add(2);
    list1.add(3);

    System.out.println(list1);
    System.out.println(list2);
    System.out.println(list3);

Sortie :

[1, 2, 3]
[1, 2, 3]
[1]

5voto

Abhishek Raj Points 69

Un objet est considéré comme immuable si son état ne peut pas changer après sa construction. Une fois que vous avez créé une instance immuable d'une collection, elle contient les mêmes données tant qu'une référence à cette collection existe.

L'un des avantages d'une collection immuable est qu'elle est automatiquement thread safe. Les collections contenant des objets immuables sont automatiquement thread safe après leur construction. Après avoir créé une telle collection, vous pouvez la confier à plusieurs threads, et ils verront tous une vue cohérente.

Cependant, une collection immuable d'objets n'est pas la même chose qu'une collection d'objets immuables. Si les éléments contenus sont mutables, la collection peut se comporter de manière incohérente ou donner l'impression que son contenu change.

En d'autres termes, si vous ajoutez un peu d'immuabilité à quelque chose de mutable, vous obtenez la mutabilité. Et si vous ajoutez un peu de mutabilité à quelque chose d'immuable, vous obtenez la mutabilité.

Immuable et non modifiable ne sont pas identiques :

Les collections immuables se comportent de la même manière que les wrappers Collections.unmodifiable.... Cependant, ces collections ne sont pas des wrappers - ce sont des structures de données implémentées par des classes où toute tentative de modification des données entraîne la levée d'une exception.

Si vous créez une liste et la passez à la méthode Collections.unmodifiableList, vous obtenez une vue non modifiable. La liste sous-jacente est toujours modifiable, et les modifications apportées sont visibles à travers la liste renvoyée, donc elle n'est pas réellement immuable.

Pour démontrer ce comportement, créez une liste et passez-la à Collections.unmodifiableList. Si vous essayez d'ajouter directement à cette liste non modifiable, une UnsupportedOperationException est levée.

Mais, si vous modifiez la liste originale, aucune erreur n'est générée, et la liste non modifiable a été modifiée.

Dans ce cas, pour rendre une collection immuable une fois qu'elle a été construite, c'est une bonne pratique de ne pas maintenir une référence à la collection de support. Cela garantit absolument l'immuabilité.

En outre, pour permettre à certains clients d'accéder en lecture seule à vos structures de données. Vous pouvez conserver une référence à la collection de sauvegarde mais distribuer une référence au wrapper. De cette façon, les clients peuvent regarder mais ne peuvent pas modifier, tandis que vous conservez un accès complet.

Ainsi, une collection immuable peut contenir des objets mutables, et si c'est le cas, la collection n'est ni immuable ni thread safe.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X