Java Language
Colecciones
Buscar..
Introducción
El marco de colecciones en java.util
proporciona una serie de clases genéricas para conjuntos de datos con una funcionalidad que no pueden ser proporcionadas por matrices regulares.
El marco de colecciones contiene interfaces para la Collection<O>
, con la lista de subinterfaces principales List<O>
y Set<O>
, y el Map<K,V>
colección de mapeo Map<K,V>
. Las colecciones son la interfaz raíz y están siendo implementadas por muchos otros marcos de colección.
Observaciones
Las colecciones son objetos que pueden almacenar colecciones de otros objetos dentro de ellos. Puede especificar el tipo de datos almacenados en una colección usando Genéricos .
Las colecciones generalmente usan los espacios de nombres java.util
o java.util.concurrent
.
Java 1.4.2 y versiones anteriores no son compatibles con los genéricos. Como tal, no puede especificar los parámetros de tipo que contiene una colección. Además de no tener seguridad de tipo, también debe usar moldes para recuperar el tipo correcto de una colección.
Además de la Collection<E>
, hay varios tipos principales de colecciones, algunas de las cuales tienen subtipos.
-
List<E>
es una colección ordenada de objetos. Es similar a una matriz, pero no define un límite de tamaño. Las implementaciones generalmente aumentarán de tamaño internamente para acomodar nuevos elementos. -
Set<E>
es una colección de objetos que no permite duplicados.-
SortedSet<E>
es unSet<E>
que también especifica el orden de los elementos.
-
-
Map<K,V>
es una colección de pares clave / valor.-
SortedMap<K,V>
es unMap<K,V>
que también especifica el orden de los elementos.
-
Java 5 agrega un nuevo tipo de colección:
-
Queue<E>
es una colección de elementos destinados a ser procesados en un orden específico. La implementación especifica si esto es FIFO o LIFO. Esto obsoleta la claseStack
.
Java 6 agrega algunos nuevos subtipos de colecciones.
-
NavigableSet<E>
es unSet<E>
con métodos de navegación especiales integrados. -
NavigableMap<K,V>
es unMap<K,V>
con métodos de navegación especiales integrados. -
Deque<E>
es unaQueue<E>
que puede leerse desde cualquier extremo.
Tenga en cuenta que los elementos anteriores son todas las interfaces. Para utilizarlos, debe encontrar las clases de implementación adecuadas, como ArrayList
, HashSet
, HashMap
o PriorityQueue
.
Cada tipo de colección tiene implementaciones múltiples que tienen diferentes métricas de rendimiento y casos de uso.
Tenga en cuenta que el principio de sustitución de Liskov se aplica a los subtipos de colección. Es decir, se puede pasar un SortedSet<E>
a una función que espera un Set<E>
. También es útil leer sobre Parámetros delimitados en la sección Genéricos para obtener más información sobre cómo usar colecciones con herencia de clase.
Si desea crear sus propias colecciones, puede ser más fácil heredar una de las clases abstractas (como AbstractList
) en lugar de implementar la interfaz.
Antes de la versión 1.2, tenías que usar las siguientes clases / interfaces en su lugar:
-
Vector
lugar deArrayList
-
Dictionary
lugar deMap
. Tenga en cuenta que el diccionario también es una clase abstracta en lugar de una interfaz. -
Hashtable
lugar deHashMap
Estas clases son obsoletas y no deben usarse en el código moderno.
Declarar una ArrayList y agregar objetos
Podemos crear un ArrayList
(siguiendo la interfaz de la List
):
List aListOfFruits = new ArrayList();
List<String> aListOfFruits = new ArrayList<String>();
List<String> aListOfFruits = new ArrayList<>();
Ahora, usa el método add
para agregar una String
:
aListOfFruits.add("Melon");
aListOfFruits.add("Strawberry");
En el ejemplo anterior, ArrayList
contendrá la String
"Melon" en el índice 0 y la String
"Strawberry" en el índice 1.
También podemos agregar varios elementos con el método addAll(Collection<? extends E> c)
List<String> aListOfFruitsAndVeggies = new ArrayList<String>();
aListOfFruitsAndVeggies.add("Onion");
aListOfFruitsAndVeggies.addAll(aListOfFruits);
Ahora "Cebolla" se coloca en el índice 0 en aListOfFruitsAndVeggies
, "Melón" está en el índice 1 y "Fresa" está en el índice 2.
Construyendo colecciones a partir de datos existentes
Colecciones estandar
Marco de Colecciones Java
Una forma sencilla de construir una List
partir de valores de datos individuales es usar el método de Arrays.asList
java.utils.Arrays
:
List<String> data = Arrays.asList("ab", "bc", "cd", "ab", "bc", "cd");
Todas las implementaciones de colección estándar proporcionan constructores que toman otra colección como un argumento que agrega todos los elementos a la nueva colección en el momento de la construcción:
List<String> list = new ArrayList<>(data); // will add data as is
Set<String> set1 = new HashSet<>(data); // will add data keeping only unique values
SortedSet<String> set2 = new TreeSet<>(data); // will add data keeping unique values and sorting
Set<String> set3 = new LinkedHashSet<>(data); // will add data keeping only unique values and preserving the original order
Marco de colecciones de guayaba de Google
Otra gran marco es Google Guava
que está clase de utilidad increíble (proporcionando métodos estáticos de conveniencia) para la construcción de diferentes tipos de colecciones estándar Lists
y Sets
:
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
...
List<String> list1 = Lists.newArrayList("ab", "bc", "cd");
List<String> list2 = Lists.newArrayList(data);
Set<String> set4 = Sets.newHashSet(data);
SortedSet<String> set5 = Sets.newTreeSet("bc", "cd", "ab", "bc", "cd");
Mapeo de Colecciones
Marco de Colecciones Java
De manera similar, para los mapas, dado un Map<String, Object> map
se puede construir un nuevo mapa con todos los elementos de la siguiente manera:
Map<String, Object> map1 = new HashMap<>(map);
SortedMap<String, Object> map2 = new TreeMap<>(map);
Marco de Apache Commons Collections
Usando Apache Commons
puede crear un mapa usando una matriz en ArrayUtils.toMap
así como MapUtils.toMap
:
import org.apache.commons.lang3.ArrayUtils;
...
// Taken from org.apache.commons.lang.ArrayUtils#toMap JavaDoc
// Create a Map mapping colors.
Map colorMap = MapUtils.toMap(new String[][] {{
{"RED", "#FF0000"},
{"GREEN", "#00FF00"},
{"BLUE", "#0000FF"}});
Cada elemento de la matriz debe ser Map.Entry o Array, que contenga al menos dos elementos, donde el primer elemento se utiliza como clave y el segundo como valor.
Marco de colecciones de guayaba de Google
La clase de utilidad del marco de Google Guava
se llama Maps
:
import com.google.common.collect.Maps;
...
void howToCreateMapsMethod(Function<? super K,V> valueFunction,
Iterable<K> keys1,
Set<K> keys2,
SortedSet<K> keys3) {
ImmutableMap<K, V> map1 = toMap(keys1, valueFunction); // Immutable copy
Map<K, V> map2 = asMap(keys2, valueFunction); // Live Map view
SortedMap<K, V> map3 = toMap(keys3, valueFunction); // Live Map view
}
Utilizando Stream
,
Stream.of("xyz", "abc").collect(Collectors.toList());
o
Arrays.stream("xyz", "abc").collect(Collectors.toList());
Unir listas
Se pueden utilizar las siguientes formas para unir listas sin modificar la (s) lista (s) de origen.
Primer enfoque. Tiene más líneas pero es fácil de entender.
List<String> newList = new ArrayList<String>();
newList.addAll(listOne);
newList.addAll(listTwo);
Segundo enfoque. Tiene una línea menos pero menos legible.
List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);
Tercer enfoque. Requiere de la biblioteca de colecciones comunes de Apache de terceros.
ListUtils.union(listOne,listTwo);
Usando Streams se puede lograr lo mismo por
List<String> newList = Stream.concat(listOne.stream(), listTwo.stream()).collect(Collectors.toList());
Referencias. Lista de interfaces
Eliminar elementos de una lista dentro de un bucle
Es difícil eliminar elementos de una lista mientras se encuentra dentro de un bucle, esto se debe al hecho de que el índice y la longitud de la lista se modifican.
Dada la siguiente lista, aquí hay algunos ejemplos que darán un resultado inesperado y otros que darán el resultado correcto.
List<String> fruits = new ArrayList<String>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Strawberry");
INCORRECTO
Extracción de iteración de for
declaración Omite "Banana":
El ejemplo de código solo imprimirá Apple
y Strawberry
. Banana
se omite porque se mueve al índice 0
vez Apple
se elimina, pero, al mismo tiempo i
se incrementa a 1
.
for (int i = 0; i < fruits.size(); i++) {
System.out.println (fruits.get(i));
if ("Apple".equals(fruits.get(i))) {
fruits.remove(i);
}
}
Eliminando en la excepción mejorada for
tiros de instrucción :
Debido a iterar sobre la colección y modificarla al mismo tiempo.
Emite: java.util.ConcurrentModificationException
for (String fruit : fruits) {
System.out.println(fruit);
if ("Apple".equals(fruit)) {
fruits.remove(fruit);
}
}
CORRECTO
Eliminando en bucle while usando un Iterator
Iterator<String> fruitIterator = fruits.iterator();
while(fruitIterator.hasNext()) {
String fruit = fruitIterator.next();
System.out.println(fruit);
if ("Apple".equals(fruit)) {
fruitIterator.remove();
}
}
La interfaz Iterator
tiene un método remove()
incorporado solo para este caso. Sin embargo, este método está marcado como "opcional" en la documentación y podría generar una UnsupportedOperationException
.
Emite: UnsupportedOperationException - si la operación de eliminación no es compatible con este iterador
Por lo tanto, es recomendable consultar la documentación para asegurarse de que esta operación sea compatible (en la práctica, a menos que la recopilación sea una inmutable obtenida a través de una biblioteca de terceros o el uso de uno de los métodos Collections.unmodifiable...()
, la operación es casi siempre soportada).
Al utilizar un Iterator
una Iterator
ConcurrentModificationException
cuando se modCount
el modCount
de la List
desde que se creó el Iterator
. Esto podría haber ocurrido en el mismo hilo o en una aplicación multihilo compartiendo la misma lista.
Un modCount
es una variable int
que cuenta el número de veces que esta lista ha sido modificada estructuralmente. Un cambio estructural significa esencialmente una operación add()
o remove()
que se invoca en el objeto Collection
(los cambios realizados por Iterator
no se cuentan). Cuando se crea el Iterator
, almacena este modCount
y en cada iteración de la List
comprueba si el modCount
actual es el mismo que cuando se creó el Iterator
. Si hay un cambio en el valor de modCount
, lanza una ConcurrentModificationException
.
Por lo tanto, para la lista declarada anteriormente, una operación como la siguiente no arrojará ninguna excepción:
Iterator<String> fruitIterator = fruits.iterator();
fruits.set(0, "Watermelon");
while(fruitIterator.hasNext()){
System.out.println(fruitIterator.next());
}
Pero agregar un nuevo elemento a la List
después de inicializar un Iterator
lanzará una ConcurrentModificationException
:
Iterator<String> fruitIterator = fruits.iterator();
fruits.add("Watermelon");
while(fruitIterator.hasNext()){
System.out.println(fruitIterator.next()); //ConcurrentModificationException here
}
Iterando hacia atrás
for (int i = (fruits.size() - 1); i >=0; i--) {
System.out.println (fruits.get(i));
if ("Apple".equals(fruits.get(i))) {
fruits.remove(i);
}
}
Esto no se salta nada. La desventaja de este enfoque es que la salida es inversa. Sin embargo, en la mayoría de los casos, elimina elementos que no importan. Nunca debes hacer esto con LinkedList
.
Iterando hacia adelante, ajustando el índice de bucle.
for (int i = 0; i < fruits.size(); i++) {
System.out.println (fruits.get(i));
if ("Apple".equals(fruits.get(i))) {
fruits.remove(i);
i--;
}
}
Esto no se salta nada. Cuando el elemento i
th se elimina de la List
, el elemento originalmente posicionado en el índice i+1
convierte en el nuevo elemento i
th. Por lo tanto, el bucle puede decrementar i
para que la siguiente iteración procese el siguiente elemento, sin saltarse.
Usando una lista de "debería ser eliminado"
ArrayList shouldBeRemoved = new ArrayList();
for (String str : currentArrayList) {
if (condition) {
shouldBeRemoved.add(str);
}
}
currentArrayList.removeAll(shouldBeRemoved);
Esta solución permite al desarrollador verificar si los elementos correctos se eliminan de forma más limpia.
En Java 8 son posibles las siguientes alternativas. Estos son más limpios y más directos si la eliminación no tiene que suceder en un bucle.
Filtrando una corriente
Una List
puede ser transmitida y filtrada. Se puede utilizar un filtro adecuado para eliminar todos los elementos no deseados.
List<String> filteredList =
fruits.stream().filter(p -> !"Apple".equals(p)).collect(Collectors.toList());
Tenga en cuenta que a diferencia de todos los otros ejemplos aquí, este ejemplo produce una nueva instancia de List
y mantiene la List
original sin cambios.
Utilizando removeIf
Ahorra la sobrecarga de construir un flujo si todo lo que se necesita es eliminar un conjunto de elementos.
fruits.removeIf(p -> "Apple".equals(p));
Colección no modificable
A veces no es una buena práctica exponer una colección interna, ya que puede provocar una vulnerabilidad de código malicioso debido a su característica mutable. Para proporcionar colecciones de "solo lectura", java proporciona sus versiones no modificables.
Una colección no modificable es a menudo una copia de una colección modificable que garantiza que la colección en sí no puede ser alterada. Los intentos de modificarlo darán como resultado una excepción UnsupportedOperationException.
Es importante notar que los objetos que están presentes dentro de la colección todavía pueden ser alterados.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MyPojoClass {
private List<Integer> intList = new ArrayList<>();
public void addValueToIntList(Integer value){
intList.add(value);
}
public List<Integer> getIntList() {
return Collections.unmodifiableList(intList);
}
}
El siguiente intento de modificar una colección no modificable generará una excepción:
import java.util.List;
public class App {
public static void main(String[] args) {
MyPojoClass pojo = new MyPojoClass();
pojo.addValueToIntList(42);
List<Integer> list = pojo.getIntList();
list.add(69);
}
}
salida:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.add(Collections.java:1055)
at App.main(App.java:12)
Iterando sobre colecciones
Iterando sobre la lista
List<String> names = new ArrayList<>(Arrays.asList("Clementine", "Duran", "Mike"));
names.forEach(System.out::println);
Si necesitamos paralelismo de uso.
names.parallelStream().forEach(System.out::println);
for (String name : names) {
System.out.println(name);
}
for (int i = 0; i < names.size(); i++) {
System.out.println(names.get(i));
}
//Creates ListIterator which supports both forward as well as backward traversel
ListIterator<String> listIterator = names.listIterator();
//Iterates list in forward direction
while(listIterator.hasNext()){
System.out.println(listIterator.next());
}
//Iterates list in backward direction once reaches the last element from above iterator in forward direction
while(listIterator.hasPrevious()){
System.out.println(listIterator.previous());
}
Iterando sobre Set
Set<String> names = new HashSet<>(Arrays.asList("Clementine", "Duran", "Mike"));
names.forEach(System.out::println);
for (Iterator<String> iterator = names.iterator(); iterator.hasNext(); ) {
System.out.println(iterator.next());
}
for (String name : names) {
System.out.println(name);
}
Iterator iterator = names.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
Iterando sobre el mapa
Map<Integer, String> names = new HashMap<>();
names.put(1, "Clementine");
names.put(2, "Duran");
names.put(3, "Mike");
names.forEach((key, value) -> System.out.println("Key: " + key + " Value: " + value));
for (Map.Entry<Integer, String> entry : names.entrySet()) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
// Iterating over only keys
for (Integer key : names.keySet()) {
System.out.println(key);
}
// Iterating over only values
for (String value : names.values()) {
System.out.println(value);
}
Iterator entries = names.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry entry = (Map.Entry) entries.next();
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
Colecciones vacias inmutables
A veces es apropiado utilizar una colección vacía inmutable. La clase Collections
proporciona métodos para obtener dichas colecciones de una manera eficiente:
List<String> anEmptyList = Collections.emptyList();
Map<Integer, Date> anEmptyMap = Collections.emptyMap();
Set<Number> anEmptySet = Collections.emptySet();
Estos métodos son genéricos y convertirán automáticamente la colección devuelta al tipo al que está asignado. Es decir, se puede asignar una invocación de, por ejemplo, emptyList()
a cualquier tipo de List
y de la misma manera para emptySet()
y emptyMap()
.
Las colecciones devueltas por estos métodos son inmutables, ya que lanzarán la UnsupportedOperationException
si intenta llamar a métodos que cambiarían su contenido ( add
, put
, etc.). Estas colecciones son útiles principalmente como sustitutos de resultados de métodos vacíos u otros valores predeterminados, en lugar de usar null
o crear objetos con new
.
Colecciones y valores primitivos
Las colecciones en Java solo funcionan para objetos. Es decir, no hay Map<int, int>
en Java. En su lugar, los valores primitivos deben encuadrarse en objetos, como en el Map<Integer, Integer>
. Java auto-boxing permitirá el uso transparente de estas colecciones:
Map<Integer, Integer> map = new HashMap<>();
map.put(1, 17); // Automatic boxing of int to Integer objects
int a = map.get(1); // Automatic unboxing.
Desafortunadamente, la sobrecarga de esto es sustancial . Un HashMap<Integer, Integer>
requerirá alrededor de 72 bytes por entrada (por ejemplo, en JVM de 64 bits con punteros comprimidos, y suponiendo que los enteros son mayores que 256, y suponiendo una carga del 50% del mapa). Debido a que los datos reales son solo 8 bytes, esto produce una sobrecarga masiva. Además, requiere dos niveles de direccionamiento indirecto (Mapa -> Entrada -> Valor) es innecesariamente lento.
Existen varias bibliotecas con colecciones optimizadas para tipos de datos primitivos (que requieren solo ~ 16 bytes por entrada con una carga del 50%, es decir, 4 veces menos memoria, y un nivel de direccionamiento indirecto menos), que pueden proporcionar beneficios sustanciales de rendimiento cuando se utilizan grandes colecciones de primitivos Valores en Java.
Eliminar elementos coincidentes de las listas utilizando Iterator.
Más arriba noté un ejemplo para eliminar elementos de una lista dentro de un bucle y pensé en otro ejemplo que podría ser útil esta vez usando la interfaz del Iterator
.
Esta es una demostración de un truco que puede ser útil cuando se trata de elementos duplicados en listas de las que desea deshacerse.
Nota: Esto solo se agrega a la eliminación de elementos de una lista dentro de un ejemplo de bucle :
Así que definamos nuestras listas como de costumbre.
String[] names = {"James","Smith","Sonny","Huckle","Berry","Finn","Allan"};
List<String> nameList = new ArrayList<>();
//Create a List from an Array
nameList.addAll(Arrays.asList(names));
String[] removeNames = {"Sonny","Huckle","Berry"};
List<String> removeNameList = new ArrayList<>();
//Create a List from an Array
removeNameList.addAll(Arrays.asList(removeNames));
El siguiente método toma dos objetos de la Colección y realiza la magia de eliminar los elementos de nuestra removeNameList
que coinciden con los elementos de nameList
.
private static void removeNames(Collection<String> collection1, Collection<String> collection2) {
//get Iterator.
Iterator<String> iterator = collection1.iterator();
//Loop while collection has items
while(iterator.hasNext()){
if (collection2.contains(iterator.next()))
iterator.remove(); //remove the current Name or Item
}
}
Al llamar al método y que pasa en la nameList
y la removeNameList
como sigue removeNames(nameList,removeNameList);
Producirá la siguiente salida:
Lista de matrices antes de eliminar nombres: James Smith Sonny Huckle Berry Finn Allan
Lista de matrices después de eliminar nombres: James Smith Finn Allan
Un uso simple y simple para colecciones que puede ser útil para eliminar elementos que se repiten en las listas.
Creando su propia estructura de Iterable para usar con Iterator o para cada bucle.
Para asegurarnos de que nuestra colección pueda iterarse utilizando iterador o para cada bucle, debemos seguir los siguientes pasos:
- Lo que queremos iterar debe ser
Iterable
y exponeriterator()
. - Diseñe un
java.util.Iterator
anulandohasNext()
,next()
yremove()
.
A continuación, agregué una implementación de lista vinculada genérica simple que utiliza las entidades anteriores para hacer que la lista vinculada sea iterable.
package org.algorithms.linkedlist;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class LinkedList<T> implements Iterable<T> {
Node<T> head, current;
private static class Node<T> {
T data;
Node<T> next;
Node(T data) {
this.data = data;
}
}
public LinkedList(T data) {
head = new Node<>(data);
}
public Iterator<T> iterator() {
return new LinkedListIterator();
}
private class LinkedListIterator implements Iterator<T> {
Node<T> node = head;
@Override
public boolean hasNext() {
return node != null;
}
@Override
public T next() {
if (!hasNext())
throw new NoSuchElementException();
Node<T> prevNode = node;
node = node.next;
return prevNode.data;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Removal logic not implemented.");
}
}
public void add(T data) {
Node current = head;
while (current.next != null)
current = current.next;
current.next = new Node<>(data);
}
}
class App {
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>(1);
list.add(2);
list.add(4);
list.add(3);
//Test #1
System.out.println("using Iterator:");
Iterator<Integer> itr = list.iterator();
while (itr.hasNext()) {
Integer i = itr.next();
System.out.print(i + " ");
}
//Test #2
System.out.println("\n\nusing for-each:");
for (Integer data : list) {
System.out.print(data + " ");
}
}
}
Salida
using Iterator:
1 2 4 3
using for-each:
1 2 4 3
Esto se ejecutará en Java 7+. Puede hacer que se ejecute en Java 5 y Java 6 también sustituyendo:
LinkedList<Integer> list = new LinkedList<>(1);
con
LinkedList<Integer> list = new LinkedList<Integer>(1);
o cualquier otra versión incorporando los cambios compatibles.
Pitfall: excepciones de modificaciones concurrentes
Esta excepción se produce cuando se modifica una colección al iterar sobre ella utilizando métodos distintos a los proporcionados por el objeto iterador. Por ejemplo, tenemos una lista de sombreros y queremos eliminar todos aquellos que tienen orejeras:
List<IHat> hats = new ArrayList<>();
hats.add(new Ushanka()); // that one has ear flaps
hats.add(new Fedora());
hats.add(new Sombrero());
for (IHat hat : hats) {
if (hat.hasEarFlaps()) {
hats.remove(hat);
}
}
Si ejecutamos este código, ConcurrentModificationException se generará ya que el código modifica la colección mientras lo iteramos. La misma excepción puede ocurrir si uno de los múltiples subprocesos que trabajan con la misma lista está intentando modificar la colección mientras que otros iteran sobre ella. La modificación simultánea de colecciones en varios subprocesos es algo natural, pero debe tratarse con las herramientas habituales de la caja de herramientas de programación concurrente, como los bloqueos de sincronización, las colecciones especiales adoptadas para la modificación concurrente, la modificación de la colección clonada desde el inicio, etc.
Sub Colecciones
Lista de sublistas (int fromIndex, int toIndex)
Aquí fromIndex es inclusivo y toIndex es exclusivo.
List list = new ArrayList();
List list1 = list.subList(fromIndex,toIndex);
- Si la lista no existe en el rango de dar, lanza la excepción IndexOutofBoundException.
- Los cambios realizados en la lista1 afectarán a los mismos cambios en la lista. Esto se denomina colecciones respaldadas.
- Si el fromnIndex es mayor que el toIndex (fromIndex> toIndex) lanza la excepción IllegalArgumentException.
Ejemplo:
List<String> list = new ArrayList<String>();
List<String> list = new ArrayList<String>();
list.add("Hello1");
list.add("Hello2");
System.out.println("Before Sublist "+list);
List<String> list2 = list.subList(0, 1);
list2.add("Hello3");
System.out.println("After sublist changes "+list);
Salida:
Antes de Sublist [Hello1, Hello2]
Después de cambios de lista [Hello1, Hello3, Hello2]
Establecer subSet (fromIndex, toIndex)
Aquí fromIndex es inclusivo y toIndex es exclusivo.
Set set = new TreeSet();
Set set1 = set.subSet(fromIndex,toIndex);
El conjunto devuelto lanzará una IllegalArgumentException en un intento de insertar un elemento fuera de su rango.
Mapa de mapa secundario (fromKey, toKey)
fromKey es inclusivo y toKey es exclusivo
Map map = new TreeMap();
Map map1 = map.get(fromKey,toKey);
Si fromKey es mayor que toKey o si este mapa en sí tiene un rango restringido, y fromKey o toKey se encuentra fuera de los límites del rango, arroja IllegalArgumentException.
Todas las colecciones admiten colecciones respaldadas significa que los cambios realizados en la sub colección tendrán el mismo cambio en la colección principal.