2009-01-06 29 views
14

menudo hago un campo de recolección no se puede modificar antes de devolverla a partir de un método de obtención:¿Cómo crear una colección profunda no modificable?

private List<X> _xs; 
.... 
List<X> getXs(){ 
    return Collections.unmodifiableList(_xs); 
} 

Pero no puedo pensar en una manera conveniente de hacer eso si el X anterior es en sí misma una lista:

private List<List<Y>> _yLists; 
..... 
List<List<Y>> getYLists() { 
    return Collections.unmodifiableList(_yLists); 
} 

El problema en lo anterior es, por supuesto, que aunque el cliente no puede modificar la Lista de listas, puede agregar/eliminar objetos Y de las listas incrustadas.

¿Alguna idea?

Respuesta

7

Lo mejor que pude encontrar utiliza ForwardingList from Google Collections. Los comentarios son bienvenidos

private static <T> List<List<T>> unmodifiableList2(final List<List<T>> input) { 
    return Collections.unmodifiableList(new ForwardingList<List<T>>() { 
     @Override protected List<List<T>> delegate() { 
      return Collections.unmodifiableList(input); 
     } 
     @Override public List<T> get(int index) { 
      return Collections.unmodifiableList(delegate().get(index)); 
     } 
    }); 
} 
+0

Eso está bastante bien. –

+0

Especialmente después de que hice la lista externa no modificable también :-) –

+1

¿Qué sucede si se trata de una lista de conjuntos? –

3

Desafortunadamente, no hay una manera fácil de obtener const-sidad profunda en java. tendrías que hackearlo asegurándote siempre de que la lista dentro de la lista tampoco sea modificable.

Me gustaría saber cualquier solución elegante.

+0

¡Y yo también! –

0

Si observa la implementación de los métodos Collections.unmodifiable * (...), puede ver que simplemente envuelven la colección. Hacer una utilidad profunda de la misma manera debería ser factible.

El inconveniente de esto es que agrega una llamada de método extra al acceso de recopilación y afecta el rendimiento.

0

Si su único objetivo aquí es hacer cumplir la encapsulación, una solución clásica es utilizar clone() o similar para devolver una estructura que no es el estado interno del objeto. Obviamente, esto solo funciona si se pueden clonar todos los objetos y si la estructura copiada es lo suficientemente pequeña.

Si esta es una estructura de datos utilizada comúnmente, otra opción es hacer que la API que accede a ella sea más concreta, para que tenga un control más detallado de las llamadas específicas. Escribir su propia implementación de lista, como se indica arriba, es uno manera de hacerlo, pero si puede reducir las llamadas a casos de uso específicos, puede exponer API de acceso específicas en lugar de la interfaz de lista.

+0

el problema con la creación de sus propias interfaces en lugar de utilizar las Java estándar es que no puede aprovechar las numerosas bibliotecas de utilidades que usan las interfaces java, a menos que las haya implementado también. En mi humilde opinión, ese es un precio demasiado alto como para pagar una constidad profunda. – Chii

+0

La colección indicada (Lista de listas) no es una colección estándar. – TREE

0

Sólo en caso de que alguien se interesa aquí es una solución simple:

public List<List<Double>> toUnmodifiable(List<List<Double>> nestedList) { 
     List<List<Double>> listWithUnmodifiableLists = new ArrayList<>(); 
      for (List<Double> list : nestedList) {    
       listWithUnmodifiableLists 
        .add(Collections.unmodifiableList(list)); 
      } 
     return Collections.unmodifiableList(listWithUnmodifiableLists); 
    } 

Esto se puede utilizar por ejemplo como una solución si quieres exponer una lista con un método getList(), puede devolver: toUnmodifiable (mNestedList), donde mNestedList es la lista privada de la clase.

Personalmente encontré esto útil al implementar una clase utilizada para analizar con GSON en Android, ya que no tiene sentido poder modificar una respuesta, en este caso el json deserializado, utilicé este método como una forma de exponer la lista con un getter y asegurarse de que la lista no se modifique.

Cuestiones relacionadas