colección [Java]

Tabla de contenido

1. Conjuntos y matrices

1. Descripción general de los datos de almacenamiento de la colección y la matriz:

2. Características del almacenamiento en matriz:

3. Desventajas del almacenamiento en matriz:

4. Ventajas del almacenamiento colectivo:

5. Clasificación de las colecciones

6. La estructura marco de la colección.

2. Interfaz de colección

1. Estructura del marco de colección de una sola columna

2. Métodos comunes de la interfaz de colección:

3. Conversión entre colección Collection y matriz

3. Interfaz de iterador y bucle foreach

1. Dos formas de recorrer la Colección:

2. La interfaz del iterador definida en el paquete java.utils: Iterator

3. Nuevas funciones de JDK 5.0: bucle for mejorado: (bucle foreach)

4. Subinterfaz de colección: Interfaz de lista

1. Características de los datos almacenados:

2. Métodos comunes:

3. Clases de implementación comunes:

4. Análisis del código fuente (dificultad)

5. Requisitos para los elementos almacenados:

6. Preguntas de la entrevista

5. Subinterfaz de colección: descripción general de la interfaz Set

1. Características de los datos almacenados:

2. Proceso de adición de elementos: (tome HashSet como ejemplo)

3. Métodos comunes

4. Clases de implementación comunes:

5. Requisitos para la clase del objeto de almacenamiento:

6. Uso de TreeSet

6. Interfaz de mapa

1. Estructura de clase de implementación común

2. Comprensión de la estructura de almacenamiento:

3. Métodos comunes

4. Descripción de la estructura de la memoria: (punto difícil)

5. Uso de TreeMap

6. Use Propiedades para leer el archivo de configuración

7. Preguntas de la entrevista

Siete, el uso de herramientas de colección.

1. Función:

2. Métodos comunes:

8. Breve descripción de la estructura de datos

1. Descripción general de la estructura de datos

2. Comprensión de estructuras de datos y algoritmos.

3. Objeto de investigación de la estructura de datos

4. Mapa mental:


1. Conjuntos y matrices

1. Descripción general de los datos de almacenamiento de la colección y la matriz:

Las colecciones y matrices son estructuras que almacenan y operan múltiples datos, denominados contenedores Java. Explicación: el almacenamiento en este momento se refiere principalmente al almacenamiento a nivel de memoria y no implica almacenamiento persistente (.txt, .jpg, .avi, en la base de datos)

2. Características del almacenamiento en matriz:

Una vez inicializado, se determina su longitud. Una vez que se define una matriz, se determina el tipo de sus elementos. Solo podemos operar en tipos específicos de datos.

Por ejemplo: String[] arr, int[] arr1,Object[] arr2

3. Desventajas del almacenamiento en matriz:

  1. Una vez inicializado, su longitud no se puede modificar.
  2. Los métodos provistos en la matriz son muy limitados y es muy inconveniente e ineficiente para operaciones como agregar, eliminar e insertar datos.
  3. La necesidad de obtener el número real de elementos en la matriz, la matriz no tiene propiedades o métodos listos para usar disponibles
  4. Las características de los datos de almacenamiento de matriz: ordenada y repetible. Por requerimientos desordenados e irrepetibles, no puede ser satisfecho.

4. Ventajas del almacenamiento colectivo:

Resuelva las desventajas de los datos de almacenamiento de matrices.

5. Clasificación de las colecciones

Las colecciones de Java se pueden dividir en dos sistemas: Colección y Mapa

  • Interfaz de colección: una sola columna de datos que define una colección de métodos para acceder a un conjunto de objetos
    • Lista: una colección ordenada y repetible de elementos
    • Conjunto: un conjunto de elementos no ordenados y no repetibles.
  • Interfaz de mapa: datos de doble columna, guardando una colección de "pares clave-valor" con una relación de mapeo

6. La estructura marco de la colección.

|----Collection接口:单列集合,用来存储一个一个的对象
     |----List接口:存储有序的、可重复的数据。  -->“动态”数组
           |----ArrayList:作为List接口的主要实现类,线程不安全的,效率高;底层采用Object[] elementData数组存储
           |----LinkedList:对于频繁的插入删除操作,使用此类效率比ArrayList效率高底层采用双向链表存储
           |----Vector:作为List的古老实现类,线程安全的,效率低;底层采用Object[]数组存储
           
     |----Set接口:存储无序的、不可重复的数据   -->数学概念上的“集合”
           |----HashSet:作为Set接口主要实现类;线程不安全;可以存null值
           		|----LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加顺序遍历;对于频繁的遍历操作,LinkedHashSet效率高于HashSet.
           |----TreeSet:可以按照添加对象的指定属性,进行排序。


|----Map:双列数据,存储key-value对的数据   ---类似于高中的函数:y = f(x)
     |----HashMap:作为Map的主要实现类;线程不安全的,效率高;存储null的key和value
          |----LinkedHashMap:保证在遍历map元素时,可以照添加的顺序实现遍历。
                    原因:在原的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。
                    对于频繁的遍历操作,此类执行效率高于HashMap。
     |----TreeMap:保证照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序
                      底层使用红黑树
     |----Hashtable:作为古老的实现类;线程安全的,效率低;不能存储null的key和value
          |----Properties:常用来处理配置文件。key和value都是String类型


复制代码

2. Interfaz de colección

  • La interfaz Collection es la interfaz principal de las interfaces List, Set y Queue. Los métodos definidos en esta interfaz se pueden usar para operar tanto la colección Set como las colecciones List y Queue.
  • JDK no proporciona ninguna implementación directa de esta interfaz, pero proporciona una implementación de subinterfaces más específicas (como: Set y List).
  • Antes de JDK 5.0, las colecciones de Java perdían los tipos de datos de todos los objetos en el contenedor y trataban todos los objetos como tipos de objetos; dado que JDK 5.0 agregó genéricos, las colecciones de Java pueden recordar los tipos de datos de los objetos en el contenedor.

1. Estructura del marco de colección de una sola columna

|----Collection接口:单列集合,用来存储一个一个的对象
     |----List接口:存储有序的、可重复的数据。  -->“动态”数组
           |----ArrayList:作为List接口的主要实现类,线程不安全的,效率高;底层采用Object[] elementData数组存储
           |----LinkedList:对于频繁的插入删除操作,使用此类效率比ArrayList效率高底层采用双向链表存储
           |----Vector:作为List的古老实现类,线程安全的,效率低;底层采用Object[]数组存储
           
     |----Set接口:存储无序的、不可重复的数据   -->数学概念上的“集合”
           |----HashSet:作为Set接口主要实现类;线程不安全;可以存null值
           		|----LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加顺序遍历;对于频繁的遍历操作,LinkedHashSet效率高于HashSet.
           |----TreeSet:可以按照添加对象的指定属性,进行排序。


复制代码

Gráfico:

2. Métodos comunes de la interfaz de colección:

  1. añadir
    • add(Object obj)
    • addAll(Collection coll)
  2. Obtener el número de elementos válidos
    • int size()
  3. colección vacía
    • void clear()
  4. ¿Es una colección vacía?
    • boolean isEmpty()
  5. ¿Contiene un elemento
    • boolean contains(Object obj): Es juzgar si es el mismo objeto a través del método equals del elemento
    • boolean containsAll(Collection c): También se compara llamando al método equals del elemento. Compara elementos de dos colecciones uno por uno
  6. borrar
    • boolean remove(Object obj): determine si es el elemento que se eliminará mediante el método de igualdad del elemento. Solo se eliminará el primer elemento encontrado
    • boolean removeAll(Collection coll): Toma la diferencia del conjunto actual
  7. Tomar la intersección de dos conjuntos.
    • boolean retainAll(Collection c): Guarda el resultado de la intersección en la colección actual sin afectar a c
  8. son iguales los conjuntos
    • boolean equals(Object obj)
  9. Convertir en una matriz de objetos
    • Object [] toArray()
  10. Obtener el valor hash del objeto de colección
-   `hashCode()`

复制代码
  1. atravesar
-   `iterator()`:返回迭代器对象,用于集合遍历

复制代码

Ejemplo de código:

@Test
public void test1() {
    Collection collection = new ArrayList();
    //1.add(Object e):将元素添加到集合中
    collection.add("ZZ");
    collection.add("AA");
    collection.add("BB");
    collection.add(123);
    collection.add(new Date());
    //2.size():获取添加元素的个数
    System.out.println(collection.size());//5
    //3.addAll(Collection coll1):将coll1集合中的元素添加到当前集合中
    Collection collection1 = new ArrayList();
    collection1.add("CC");
    collection1.add(213);
    collection.addAll(collection1);
    System.out.println(collection.size());//9
    //调用collection1中的toString()方法输出
    System.out.println(collection);//[ZZ, AA, BB, 123, Tue Apr 28 09:22:34 CST 2020, 213, 213]
    //4.clear():清空集合元素
    collection1.clear();
    System.out.println(collection1.size());//0
    System.out.println(collection1);//[]
    //5.isEmpty():判断当前集合是否为空
    System.out.println(collection1.isEmpty());//true
}

@Test
public void test2() {
    Collection coll = new ArrayList();
    coll.add(123);
    coll.add(456);
    coll.add(new Person("Tom", 23));
    coll.add(new Person("Jarry", 34));
    coll.add(false);
    //6.contains(Object obj):判断当前集合中是否包含obj
    //判断时需要调用obj对象所在类的equals()方法
    System.out.println(coll.contains(123));//true
    System.out.println(coll.contains(new Person("Tom", 23)));//true
    System.out.println(coll.contains(new Person("Jarry", 23)));//false
    //7.containsAll(Collection coll1):判断形参coll1中的元素是否都存在当前集合中
    Collection coll1 = Arrays.asList(123, 4566);
    System.out.println(coll.containsAll(coll1));//flase
    //8.remove(Object obj):从当前集合中移除obj元素
    coll.remove(123);
    System.out.println(coll);//[456, Person{name='Tom', age=23}, Person{name='Jarry', age=34}, false]
    //9.removeAll(Collection coll1):差集:从当前集合中和coll1中所有的元素
    Collection coll2 = Arrays.asList(123, 456, false);
    coll.removeAll(coll2);
    System.out.println(coll);//[Person{name='Tom', age=23}, Person{name='Jarry', age=34}]
}

@Test
public void test3() {
    Collection coll = new ArrayList();
    coll.add(123);
    coll.add(456);
    coll.add(new Person("Tom", 23));
    coll.add(new Person("Jarry", 34));
    coll.add(false);
    //10.retainAll(Collection coll1):交集:获取当前集合和coll1集合的交集,并返回给当前集合
    Collection coll1 = Arrays.asList(123, 345, 456);
    boolean b = coll.retainAll(coll1);
    System.out.println(b);//true
    System.out.println(coll);//[123, 456]
    //11.equals(Object obj):返回true需要当前集合和形参集合的元素相同
    Collection coll2 = new ArrayList();
    coll2.add(123);
    coll2.add(456);
    System.out.println(coll.equals(coll2));//true
    //12.hashCode():返回当前对象的哈希值
    System.out.println(coll.hashCode());//5230
    //13.集合--->数组:toArray()
    Object[] array = coll.toArray();
    for (Object obj : array) {
        System.out.println(obj);
    }
    //14.数组--->集合:调用Arrays类的静态方法asList()
    List<int[]> ints = Arrays.asList(new int[]{123, 345});
    System.out.println(ints.size());//1
    List<String> strings = Arrays.asList("AA", "BB", "CC");
    System.out.println(strings);//[AA, BB, CC]
    //15.iteratoriterator():返回Iterator接口的实例,用于遍历集合元素。
}


复制代码

3. Conversión entre colección Collection y matriz

//集合 --->数组:toArray()
Object[] arr = coll.toArray();
for(int i = 0;i < arr.length;i++){
    System.out.println(arr[i]);
}

//拓展:数组 --->集合:调用Arrays类的静态方法asList(T ... t)
List<String> list = Arrays.asList(new String[]{"AA", "BB", "CC"});
System.out.println(list);

List arr1 = Arrays.asList(new int[]{123, 456});
System.out.println(arr1.size());//1

List arr2 = Arrays.asList(new Integer[]{123, 456});
System.out.println(arr2.size());//2


复制代码

Para usar Collection para almacenar objetos, la clase a la que pertenece el objeto debe cumplir con:

Al agregar datos obj al objeto de la clase de implementación de la interfaz Collection, se requiere reescribir la clase donde se requiere obj  equals().

3. Interfaz de iterador y bucle foreach

1. Dos formas de recorrer la Colección:

① Usar iterador Iterador

② bucle foreach (o bucle for mejorado)

2. La interfaz del iterador definida en el paquete java.utils: Iterator

2.1 Descripción:

El objeto Iterator se denomina iterador (un tipo de patrón de diseño) y se utiliza principalmente para recorrer los elementos de la colección Collection. GOF define el patrón de iterador como: proporcionar un método para acceder a cada elemento en un objeto contenedor sin exponer los detalles internos del objeto. El patrón iterador nace para los contenedores.

2.2 Función:

Colección transversal Elementos de la colección

2.3 Cómo obtener una instancia:

coll.iterator() devuelve una instancia de iterador

2.4 Código de implementación de cruce:

Iterator iterator = coll.iterator();
//hasNext():判断是否还下一个元素
while(iterator.hasNext()){
    //next():①指针下移 ②将下移以后集合位置上的元素返回
    System.out.println(iterator.next());
}


复制代码

2.5 Ilustraciones:

2.6 Uso del método remove() en el iterador:

  • Probar el iterador en remove()
  • Si el método no ha sido llamado  o el método  ha sido llamado después  next() de la última llamada al método   , informará si llama a remove nuevamente  .next()remove()IllegalStateException
  • Definidos internamente  remove(), los elementos de la colección se pueden eliminar durante el recorrido. Este método es diferente de la colección que llama directamenteremove()

Ejemplo de código:

@Test
public void test3(){
    Collection coll = new ArrayList();
    coll.add(123);
    coll.add(456);
    coll.add(new Person("Jerry",20));
    coll.add("Tom"
            );
    coll.add(false);

    //删除集合中"Tom"
    Iterator iterator = coll.iterator();
    while (iterator.hasNext()){
        //            iterator.remove();
        Object obj = iterator.next();
        if("Tom".equals(obj)){
            iterator.remove();
            //                iterator.remove();
        }

    }
    //将指针重新放到头部,遍历集合
    iterator = coll.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
}


复制代码

3. Nuevas funciones de JDK 5.0: bucle for mejorado: (bucle foreach)

3.1 Ejemplo de recorrido de colecciones:

@Test
public void test1(){
    Collection coll = new ArrayList();
    coll.add(123);
    coll.add(456);
    coll.add(new Person("Jerry",20));
    coll.add(new String("Tom"));
    coll.add(false);

    //for(集合元素的类型 局部变量 : 集合对象)
    
    for(Object obj : coll){
        System.out.println(obj);
    }
}


复制代码

Explicación: El iterador todavía se llama internamente.

3.2 Ejemplo de recorrido de un arreglo:

@Test
public void test2(){
    int[] arr = new int[]{1,2,3,4,5,6};
    //for(数组元素的类型 局部变量 : 数组对象)
    for(int i : arr){
        System.out.println(i);
    }
}


复制代码

4. Subinterfaz de colección: Interfaz de lista

1. Características de los datos almacenados:

Almacene datos secuenciales y repetibles.

  • En vista de las limitaciones de las matrices utilizadas para almacenar datos en Java, generalmente usamos List en lugar de matrices.
  • Los elementos de la clase de colección List están ordenados y son repetibles, y cada elemento de la colección tiene su índice secuencial correspondiente.
  • Los elementos en el contenedor Lista corresponden a un número de serie entero para registrar su posición en el contenedor, y se puede acceder a los elementos en el contenedor según el número de serie.
  • Las clases de implementación comunes de la interfaz List en JDK AP son: ArrayList, LinkedList y Vector.

2. Métodos comunes:

Además de los métodos heredados de la colección Collection, la colección List agrega algunos métodos para manipular los elementos de la colección en función del índice.

  • void add(int index, Object ele): inserta el elemento ele en la posición de índice
  • boolean addAll(int index, Collection eles): Agregue todos los elementos en eles desde la posición del índice
  • Object get(int index): Obtener el elemento en la posición de índice especificada
  • int indexOf(Object obj): Devuelve la posición donde obj aparece por primera vez en la colección
  • int lastIndexOf(Object obj): Devuelve la última aparición de obj en la colección actual
  • Object remove(int index): elimina el elemento en la posición de índice especificada y devuelve este elemento
  • Object set(int index, Object ele): establece el elemento en la posición de índice especificada en ele
  • List subList(int fromIndex, int toIndex): Devuelve la subcolección de fromIndex a toIndex

Resumir:

  • aumentar:add(Object obj)
  • eliminar: remove(int index) / remove(Object obj)
  • cambiar:set(int index, Object ele)
  • controlar:get(int index)
  • Insertar:add(int index, Object ele)
  • longitud:size()
  • Recorrido: ① Método iterador iterador ② foreach (bucle for mejorado) ③ Bucle ordinario

Ejemplo de código:

@Test
public void test2(){
    ArrayList list = new ArrayList();
    list.add(123);
    list.add(456);
    list.add("AA");
    list.add(new Person("Tom",12));
    list.add(456);
    //int indexOf(Object obj):返回obj在集合中首次出现的位置。如果不存在,返回-1.
    int index = list.indexOf(4567);
    System.out.println(index);

    //int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置。如果不存在,返回-1.
    System.out.println(list.lastIndexOf(456));

    //Object remove(int index):移除指定index位置的元素,并返回此元素
    Object obj = list.remove(0);
    System.out.println(obj);
    System.out.println(list);

    //Object set(int index, Object ele):设置指定index位置的元素为ele
    list.set(1,"CC");
    System.out.println(list);

    //List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的左闭右开区间的子集合
    List subList = list.subList(2, 4);
    System.out.println(subList);
    System.out.println(list);
}


@Test
public void test1(){
    ArrayList list = new ArrayList();
    list.add(123);
    list.add(456);
    list.add("AA");
    list.add(new Person("Tom",12));
    list.add(456);

    System.out.println(list);

    //void add(int index, Object ele):在index位置插入ele元素
    list.add(1,"BB");
    System.out.println(list);

    //boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
    List list1 = Arrays.asList(1, 2, 3);
    list.addAll(list1);
    //        list.add(list1);
    System.out.println(list.size());//9

    //Object get(int index):获取指定index位置的元素
    System.out.println(list.get(0));

}


复制代码

3. Clases de implementación comunes:

3. 常用实现类:
|----Collection接口:单列集合,用来存储一个一个的对象
  |----List接口:存储序的、可重复的数据。  -->“动态”数组,替换原的数组
      |----ArrayList:作为List接口的主要实现类;线程不安全的,效率高;底层使用Object[] elementData存储
      |----LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用双向链表存储
      |----Vector:作为List接口的古老实现类;线程安全的,效率低;底层使用Object[] elementData存储


复制代码

3.1 Lista de matrices

  • ArrayList es una clase de implementación típica de la interfaz List, la clase de implementación principal
  • Esencialmente, ArrayList es una matriz de referencias de objetos de "longitud variable".
  • ¿Cuál es la diferencia entre la implementación de Array Listi antes y después de JDK 1.8?
    • JDK 1.7: ArrayList es como un hombre hambriento, creando directamente una matriz con una capacidad inicial de 10
    • JDK 1.8: ArrayList es como un hombre perezoso, crea una matriz con una longitud de 0 al principio y crea una matriz con una capacidad inicial de 10 al agregar el primer elemento
  • Arrays.asList(...)La colección List devuelta por el método no es una instancia de ArrayList ni una instancia de Vector. Arrays.asList(...)El valor devuelto es una colección List de longitud fija

Ejemplo de código:

@Test
public void test1() {
    Collection coll = new ArrayList();
    coll.add(123);
    coll.add(345);
    coll.add(new User("Tom", 34));
    coll.add(new User("Tom"));
    coll.add(false);
    //iterator()遍历ArrayList集合
    Iterator iterator = coll.iterator();
    while (iterator.hasNext()) {
        System.out.println(iterator.next());
    }
}


复制代码

3.2 lista enlazada

  • Para la inserción y eliminación frecuente de elementos, se recomienda utilizar la clase LinkedList, que es más eficiente

  • Nuevo método:

    • void addFirst(Object obj)
    • void addLast(Object obj)
    • Object getFirst()
    • Object getlast)()
    • Object removeFirst()
    • Object removeLast()
  • Lista enlazada: una lista doblemente enlazada. En lugar de declarar una matriz dentro, define el primero y el último del tipo de nodo para registrar el primer y el último elemento. Al mismo tiempo, defina el Nodo de clase interna como la estructura básica para guardar datos en Linkedlist. Además de guardar datos, Node también define dos variables:

    • prev: La variable registra la posición del elemento anterior
    • siguiente: La variable registra la posición del siguiente elemento

Ejemplo de código:

@Test
public void test3(){
    LinkedList linkedList = new LinkedList();
    linkedList.add(123);
    linkedList.add(345);
    linkedList.add(2342);
    linkedList.add("DDD");
    linkedList.add("AAA");
    
    Iterator iterator = linkedList.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
}


复制代码

4. Análisis del código fuente (dificultad)

4.1 Análisis del código fuente de ArrayList:

4.1.1 En el caso de JDK 7.0

ArrayList list = new ArrayList();//底层创建了长度是10的Object[]数组elementData
list.add(123);//elementData[0] = new Integer(123);
...
list.add(11);//如果此次的添加导致底层elementData数组容量不够,则扩容。


复制代码
  • De forma predeterminada, la expansión es 1,5 veces la capacidad original y los datos del arreglo original deben copiarse en el nuevo arreglo.

  • Conclusión: Se recomienda utilizar constructores con parámetros en desarrollo:ArrayList list = new ArrayList(int capacity)

4.1.2 Cambios de ArrayList en JDK 8.0:

ArrayList list = new ArrayList();//底层Object[] elementData初始化为{}.并没创建长度为10的数组
list.add(123);//第一次调用add()时,底层才创建了长度10的数组,并将数据123添加到elementData[0]
...


复制代码

Las operaciones posteriores de adición y expansión no son diferentes de JDK 7.0.

4.1.3 Resumen:

La creación de objetos ArrayList en JDK 7.0 es similar al estilo hambriento de singletons, mientras que la creación de objetos ArrayList en JDK 8.0 es similar al estilo perezoso de singletons, que retrasa la creación de matrices y ahorra memoria.

4.2 Análisis del código fuente de LinkedList:

LinkedList list = new LinkedList(); //内部声明了Node类型的first和last属性,默认值为null
list.add(123);//将123封装到Node中,创建了Node对象。

//其中,Node定义为:体现了LinkedList的双向链表的说法
private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;

    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}


复制代码

4.3 Análisis del código fuente de Vector:

  • Vector es una colección antigua, JDK 1.0 tendrá. La mayoría de las operaciones son las mismas que ArrayList, la diferencia es que Vector es seguro para subprocesos
  • Entre varias listas, es mejor usar ArrayList como opción predeterminada. Cuando la inserción y la eliminación sean frecuentes, use LinkedList; Vector siempre es más lento que ArrayList, así que trate de evitar usarlo.
  • Al crear un objeto a través del constructor Vector() en JDK 7.0 y JDK 8.0, se crea una matriz con una longitud de 10 en la capa inferior.
  • En términos de expansión, la expansión predeterminada es el doble de la longitud de la matriz original.

5. Requisitos para los elementos almacenados:

El objeto agregado, la clase donde se encuentra debe anular el método equals()

6. Preguntas de la entrevista

¿Puedo preguntar las similitudes y diferencias de ArrayList/LinkedList/Vector? ¿Hablar de tu comprensión? ¿Cuál es la capa inferior de ArrayList? ¿Mecanismo de expansión? ¿La mayor diferencia entre Vector y ArrayList?

  • Las similitudes y diferencias entre ArrayList y Linkedlist:

    Ambos son inseguros para subprocesos. En comparación con Vector seguro para subprocesos, ArrayList tiene una mayor eficiencia de ejecución. Además, ArrayList implementa una estructura de datos basada en una matriz dinámica y Linkedlist se basa en una estructura de datos de lista enlazada. Para obtener y establecer acceso aleatorio, ArrayList es mejor que Linkedlist, porque Linkedlist necesita mover el puntero. Para agregar y eliminar operaciones agregar (específicamente insertar) y eliminar, Linkedlist tiene una ventaja porque ArrayList necesita mover datos.

  • La diferencia entre ArrayList y Vector:

    Vector y ArrayList son casi idénticos, la única diferencia es que Vector es una clase sincronizada (synchronized), que pertenece a la clase de sincronización fuerte. Por lo tanto, la sobrecarga es mayor que la de ArrayList y el acceso es más lento. En circunstancias normales, la mayoría de los programadores de Java usan ArrayList en lugar de Vector, porque el programador puede controlar completamente la sincronización. Vector solicita 2 veces su tamaño cada vez que se expande, mientras que ArrayList requiere 1,5 veces. Vector también tiene una subclase Stack.

5. Subinterfaz de colección: descripción general de la interfaz Set

  • La interfaz Set es una subinterfaz de Collection, y la interfaz set no proporciona métodos adicionales
  • La colección Set no puede contener los mismos elementos. Si intenta agregar dos elementos idénticos a la misma colección Set, la operación de adición fallará. (Se usa principalmente para filtrar operaciones y eliminar datos duplicados)
  • Set determina si dos objetos son iguales sin usar el operador ==, pero de acuerdo con el método equals()

1. Características de los datos almacenados:

Se utiliza para almacenar elementos desordenados y no repetibles.

Tome HashSet como ejemplo:

  1. Desorden: No es igual a la aleatoriedad. Los datos almacenados no se agregan en el orden del índice de matriz en la matriz subyacente, sino que se determinan de acuerdo con el valor hash de los datos.
  2. No repetibilidad: asegúrese de que el elemento agregado no pueda devolver verdadero cuando se juzgue por equals (). Es decir: solo se puede agregar uno del mismo elemento.

2. Proceso de adición de elementos: (tome HashSet como ejemplo)

Agregamos el elemento a a HashSet, primero llamamos al método hashCode() de la clase a la que pertenece el elemento a para calcular el valor hash del elemento a, y luego calculamos la ubicación de almacenamiento en la matriz subyacente de HashSet a través de un cierto algoritmo para este valor hash (es decir, : posición de índice), a juzgar

Si la matriz ya tiene un elemento en esta posición:

  • Si no hay ningún otro elemento en esta posición, el elemento a se agrega con éxito. ---> Caso 1
  • Si hay otro elemento b (o varios elementos en forma de una lista enlazada) en esta posición, compare los valores hash del elemento a y el elemento b:
    • Si los valores hash no son los mismos, el elemento a se agrega con éxito. ---> Caso 2
    • Si los valores hash son los mismos, debe llamar al método equals() de la clase donde se encuentra el elemento a:
      • equals() devuelve verdadero, el elemento a no se pudo agregar
      • equals() devuelve falso, luego el elemento a se agrega con éxito. ---> Caso 3

Para los casos 2 y 3 en los que la adición es exitosa: el elemento a y los datos que ya existen en la posición de índice especificada se almacenan en forma de lista enlazada.

JDK 7.0: el elemento a se coloca en la matriz y apunta al elemento original.

JDK 8.0: el elemento original está en la matriz, apuntando al elemento a

Resumen: altibajos

La capa inferior de HashSet: la estructura de matriz + lista vinculada. (antes de JDK 7.0)

3. Métodos comunes

No hay nuevos métodos adicionales definidos en la interfaz Set y se utilizan todos los métodos declarados en Collection.

3.1 El método básico para reescribir hashCode()

  • Cuando el programa se está ejecutando, llamar  hashCode() al método varias veces en el mismo objeto debería devolver el mismo valor.

  • Cuando la comparación de métodos de dos objetos  devuelve verdadero,  los valores de retorno de los métodos equals() de estos dos objetos  también deben ser iguales.hashCode()

  • El campo utilizado para la comparación de métodos en el objeto  equals() debe usarse para calcular el valor de hashCode.

3.2  equals() Principios básicos de los métodos de anulación

  • Tomando la clase Customer personalizada como ejemplo, ¿cuándo necesita ser reescrita  equals()?

  • Cuando una clase tiene su propio concepto único de "igualdad lógica”, al reescribir equals(), siempre debe reescribirse.  hash Code()De acuerdo con el método equals de una clase (después de reescribir), dos instancias completamente diferentes pueden ser lógicamente iguales, pero, según el  Object.hashCode() método, son sólo dos objetos.

  • Por lo tanto, los objetos que violan la igualdad deben tener códigos hash iguales .

  • Conclusión: al reescribir el método equals, generalmente es necesario reescribir el método hashCode al mismo tiempo. Por lo general, las propiedades del objeto involucrado en el cálculo de hashCode también deberían estar involucradas en  equals() el cálculo.

3.3 reescritura de hashCode() en herramientas Eclipse/IDEA

Tomando Eclipse/DEA como ejemplo, se pueden llamar herramientas para reescribir  equals() y hashCode()

Pregunta: ¿Por qué hay un número de 31 al reescribir el método de código hash con Eclipse/IDEA?

  • Al seleccionar el coeficiente, elija el coeficiente más grande posible. Porque si la dirección hash calculada es más grande, los llamados "conflictos" serán menores y se mejorará la eficiencia de la búsqueda. (menos conflicto)

  • Y 31 solo ocupa 5 bits, la probabilidad de desbordamiento de datos causado por la multiplicación es pequeña.

  • 31 se puede representar mediante i*31==(<<5)-1, y ahora muchas máquinas virtuales tienen optimizaciones relacionadas. (mejorar la eficiencia del algoritmo)

  • 31 es un número primo. La función de un número primo es que si multiplico este número primo por un número, el resultado final solo puede ser divisible por el propio número primo, el multiplicando y 1. (menos conflicto)

Ejemplo de código:

@Override
public boolean equals(Object o) {
    System.out.println("User equals()....");
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    User user = (User) o;

    if (age != user.age) return false;
    return name != null ? name.equals(user.name) : user.name == null;
}

@Override
public int hashCode() { //return name.hashCode() + age;
    int result = name != null ? name.hashCode() : 0;
    result = 31 * result + age;
    return result;
}


复制代码

4. Clases de implementación comunes:

 |----Collection接口:单列集合,用来存储一个一个的对象
      |----Set接口:存储无序的、不可重复的数据   -->高中讲的“集合”
           |----HashSet:作为Set接口的主要实现类;线程不安全的;可以存储null值
                |----LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历,对于频繁的遍历操作,LinkedHashSet效率高于HashSet.
           |----TreeSet:可以按照添加对象的指定属性,进行排序。


复制代码

4.1 HashSet

  • Hashset es una implementación típica de la interfaz Set, y esta clase de implementación se usa la mayor parte del tiempo cuando se usa la colección Set.
  • HashSet almacena los elementos de la colección de acuerdo con el algoritmo Hash, por lo que tiene un buen rendimiento de acceso, búsqueda y eliminación.
  • HashSet tiene las siguientes características:
    • El orden de los elementos no está garantizado.
    • HashSet no es seguro para subprocesos
    • Los elementos de la colección pueden ser nulos
  • HashSet establece los criterios para juzgar la igualdad de dos elementos: el método hashCode() compara dos objetos iguales y los valores de retorno del método equals() de los dos objetos también son iguales.
  • Para los objetos almacenados en el contenedor Set, la clase correspondiente debe reescribir los métodos equals() y hashCode(Object obj) para implementar la regla de igualdad de objetos. Es decir: "Los objetos iguales deben tener códigos hash iguales"

Ejemplo de código:

@Test
//HashSet使用
public void test1(){
    Set set = new HashSet();
    set.add(454);
    set.add(213);
    set.add(111);
    set.add(123);
    set.add(23);
    set.add("AAA");
    set.add("EEE");
    set.add(new User("Tom",34));
    set.add(new User("Jarry",74));

    Iterator iterator = set.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
}


复制代码

4.2 Conjunto de hash vinculado

  • LinkedhashSet es una subclase de HashSet

  • LinkedhashSet determina la ubicación de almacenamiento del elemento según el valor hashCode del elemento, pero también utiliza una lista doblemente vinculada para mantener el orden de los elementos, lo que hace que los elementos parezcan estar almacenados en el orden de inserción.

  • El rendimiento de inserción de LinkedhashSet es ligeramente inferior al de HashSet, pero tiene un buen rendimiento al iterar a través de todos los elementos de Set.

  • LinkedhashSet no permite elementos de colección duplicados.

Gráfico:

Ejemplo de código:

@Test
//LinkedHashSet使用
public void test2(){
    Set set = new LinkedHashSet();
    set.add(454);
    set.add(213);
    set.add(111);
    set.add(123);
    set.add(23);
    set.add("AAA");
    set.add("EEE");
    set.add(new User("Tom",34));
    set.add(new User("Jarry",74));

    Iterator iterator = set.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
}


复制代码

4.3 Conjunto de árboles

  • Treeset es una clase de implementación de la interfaz SortedSet, y TreeSet puede garantizar que los elementos de la colección estén ordenados.

  • La capa inferior de TreeSet utiliza una estructura de árbol rojo-negro para almacenar datos

  • El método recién agregado es el siguiente: (comprender)

    • Comparator comparator()

    • Object first()

    • Object last()

    • Object lower(object e)

    • Object higher(object e)

    • SortedSet subSet(fromElement, toElement)

    • SortedSet headSet(toElement)

    • SortedSet tailSet(fromElement)

  • TreeSet tiene dos métodos de clasificación: clasificación natural y clasificación personalizada. De forma predeterminada, TreeSet adopta un orden natural.

Diagrama de árbol rojo-negro:

Las características del árbol rojo-negro: ordenado, la eficiencia de consulta es más rápida que la Lista

Introducción detallada: www.cnblogs.com/LiaHon/p/11…

Ejemplo de código:

@Test
public void test1(){
    Set treeSet = new TreeSet();
    treeSet.add(new User("Tom",34));
    treeSet.add(new User("Jarry",23));
    treeSet.add(new User("mars",38));
    treeSet.add(new User("Jane",56));
    treeSet.add(new User("Jane",60));
    treeSet.add(new User("Bruce",58));

    Iterator iterator = treeSet.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
}


复制代码

5. Requisitos para la clase del objeto de almacenamiento:

5.1HashSet/LinkedHashSet:

  • Requisitos: para los datos agregados a Set (principalmente se refiere a: HashSet, LinkedHashSet), la clase debe reescribir hashCode() y equals()
  • Requisitos: el hashCode() y equals() reescritos son lo más consistentes posible: los objetos iguales deben tener códigos hash iguales

Sugerencias para anular los dos métodos: el campo utilizado en el objeto para la comparación por el método equals() debe usarse para calcular el valor de hashCode.

5.2 Conjunto de árbol:

  1. En la clasificación natural, el estándar para comparar si dos objetos son iguales es: compareTo() devuelve 0. Ya no equals()

  2. En la clasificación personalizada, el estándar para comparar si dos objetos son iguales es: compare() devuelve 0. Ya no equals()

6. Uso de TreeSet

6.1 Instrucciones de uso:

  1. Se requiere que los datos agregados al TreeSet sean objetos de la misma clase.

  2. Dos métodos de clasificación: clasificación natural (implementación de la interfaz Comparable y clasificación personalizada (Comparador)

6.2 Métodos de clasificación comúnmente utilizados:

Método 1: clasificación natural

  • Clasificación natural: TreeSet llamará  compareTo(object obj) al método de los elementos de la colección para comparar la relación de tamaño entre los elementos y luego organizará los elementos de la colección en orden ascendente (por defecto)

  • Si intenta agregar un objeto al Treeset, la clase del objeto debe implementar la interfaz Comparable.

    • La clase que implementa Comparable debe implementar  compareTo(Object obj) el método, y los dos objetos se compareTo(Object obj) comparan por el valor de retorno del método.
  • Una implementación típica de Comparable:

    • BigDecimal, BigInteger y todas las clases contenedoras correspondientes a tipos numéricos: compare según sus tamaños numéricos correspondientes

    • Personaje: unic por personaje! oda valor para comparar

    • Booleano: la instancia de la clase contenedora correspondiente a verdadero es mayor que la instancia de la clase contenedora correspondiente a falso

    • Cadena: compare por el valor Unicode de los caracteres en la cadena

    • Fecha, hora: la hora y la fecha posteriores son mayores que la hora y la fecha anteriores

  • Al agregar elementos al TreeSet, solo el primer elemento no necesita el  compareTo() método de comparación, y todos los elementos agregados más tarde llamarán  compareTo() al método de comparación.

  • Debido a que solo dos instancias de la misma clase se compararán en tamaño, los objetos de la misma clase deben agregarse al TreeSet. Para la colección TreeSet, el único criterio para juzgar si dos objetos son iguales es:  compareTo(Object obj) el valor de retorno de los dos objetos a través de la comparación de métodos.

  • Cuando necesite colocar un objeto en el TreeSet y reescribir el método equals() correspondiente al objeto, debe asegurarse de que el método  compareTo(Object obj) tenga el mismo resultado que el método: si dos objetos devuelven verdadero a través de la comparación del método equals() , luego use  compareTo(object ob) la comparación de métodos Debería devolver 0. De lo contrario, es difícil de entender.

@Test
public void test1(){
    TreeSet set = new TreeSet();

    //失败:不能添加不同类的对象
    //        set.add(123);
    //        set.add(456);
    //        set.add("AA");
    //        set.add(new User("Tom",12));

    //举例一:
    //        set.add(34);
    //        set.add(-34);
    //        set.add(43);
    //        set.add(11);
    //        set.add(8);

    //举例二:
    set.add(new User("Tom",12));
    set.add(new User("Jerry",32));
    set.add(new User("Jim",2));
    set.add(new User("Mike",65));
    set.add(new User("Jack",33));
    set.add(new User("Jack",56));


    Iterator iterator = set.iterator();
    while(iterator.hasNext()){
        System.out.println(iterator.next());
    }

}


复制代码

Método 2: clasificación personalizada

  • La clasificación natural de TreeSet requiere que la clase a la que pertenece el elemento implemente la interfaz Comparable.Si la clase a la que pertenece el elemento no implementa la interfaz Comparable, o si no desea organizar los elementos en orden ascendente (por defecto ) o desea ordenar por otros tamaños de atributos, considere usar una clasificación personalizada . La clasificación personalizada se implementa a través de la interfaz Comparator. El método compare(T o1, T o2) necesita ser reescrito.

  • Use  int compare(T o1,T o2) el método para comparar el tamaño de o1 y o2: si el método devuelve un número entero positivo, significa que o1 es mayor que o2; si devuelve 0, significa que son iguales; si devuelve un número entero negativo, significa que o1 es más pequeño que o2.

  • Para implementar la ordenación personalizada, se debe pasar una instancia que implemente la interfaz Comparator como un parámetro formal al constructor TreeSet.

  • En este punto, solo se pueden agregar objetos del mismo tipo al Treeset. De lo contrario,  se produce ClassCastException una excepción .

  • El estándar para juzgar la igualdad de dos elementos usando la ordenación personalizada es: comparar dos elementos a través del Comparator devuelve 0

@Test
public void test2(){
    Comparator com = new Comparator() {
        //照年龄从小到大排列
        @Override
        public int compare(Object o1, Object o2) {
            if(o1 instanceof User && o2 instanceof User){
                User u1 = (User)o1;
                User u2 = (User)o2;
                return Integer.compare(u1.getAge(),u2.getAge());
            }else{
                throw new RuntimeException("输入的数据类型不匹配");
            }
        }
    };

    TreeSet set = new TreeSet(com);
    set.add(new User("Tom",12));
    set.add(new User("Jerry",32));
    set.add(new User("Jim",2));
    set.add(new User("Mike",65));
    set.add(new User("Mary",33));
    set.add(new User("Jack",33));
    set.add(new User("Jack",56));

    Iterator iterator = set.iterator();
    while(iterator.hasNext()){
        System.out.println(iterator.next());
    }
}


复制代码

6. Interfaz de mapa

  • El mapa y la colección existen uno al lado del otro. Se utiliza para guardar datos con una relación de mapeo: clave-valor
  • Tanto la clave como el valor en Map pueden ser datos de cualquier tipo de referencia
  • La clave en el Mapa se almacena en un conjunto y no se permite la duplicación, es decir, la clase correspondiente al mismo objeto del Mapa debe reescribir  hashCode() y  equals() método
  • La clase String se usa a menudo como la "clave" del Mapa
  • Existe una relación unidireccional entre clave y valor, es decir, siempre se puede encontrar un valor único y definido a través de la clave especificada.
  • Clases de implementación comunes de la interfaz Map: HashMap, TreeMap, LinkedHashMap y Properties. Entre ellos, HashMap es la clase de implementación más utilizada de la interfaz Map.

1. Estructura de clase de implementación común

|----Map:双列数据,存储key-value对的数据   ---类似于高中的函数:y = f(x)
     |----HashMap:作为Map的主要实现类;线程不安全的,效率高;存储null的key和value
          |----LinkedHashMap:保证在遍历map元素时,可以照添加的顺序实现遍历。
                    原因:在原的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。
                    对于频繁的遍历操作,此类执行效率高于HashMap。
     |----TreeMap:保证照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序
                      底层使用红黑树
     |----Hashtable:作为古老的实现类;线程安全的,效率低;不能存储null的key和value
          |----Properties:常用来处理配置文件。key和value都是String类型


HashMap的底层: 数组+链表  (JDK 7.0及之前)
               数组+链表+红黑树 (JDK 8.0以后)


复制代码

1.1 Mapa hash

  • HashMap es la clase de implementación más utilizada de la interfaz Map.

  • Se permiten claves nulas y valores nulos, y al igual que HashSet, no se garantiza el orden del mapeo.

  • La colección de todas las claves es un conjunto: desordenado y no repetible. Por lo tanto, la clase donde se encuentra la clave debe reescribir equals() y hashCode()

  • La colección de todos los valores es Colección: desordenada y repetible. Por lo tanto, se debe reescribir la clase donde se encuentra el valor: equals()

  • Un valor-clave constituye una entrada

  • El conjunto de todas las entradas es Conjunto: desordenado y no repetible

  • El estándar para que HashMap juzgue que dos claves son iguales es: las dos claves  equals() devuelven verdadero a través del método y los valores de hashCode también son iguales.

  • El estándar para que HashMap juzgue que dos valores son iguales es: los dos valores  equals() devuelven verdaderos a través del método.

Ejemplo de código:

@Test
public void test1(){
    Map map = new HashMap();

    map.put(null,123);

}


复制代码

1.2 Mapa hash vinculado

  • La estructura subyacente de LinkedHashMap es la misma que la de HashMap, porque LinkedHashMap hereda de HashMap.
  • La diferencia es que LinkedHashMap proporciona Entry inside, reemplazando Node en HashMap.
  • Similar a Linkedhash Set, LinkedHashMap puede mantener el orden de iteración de Map: el orden de iteración es consistente con el orden de inserción de pares clave-valor

Ejemplo de código:

@Test
public void test2(){
    Map map = new LinkedHashMap();
    map.put(123,"AA");
    map.put(345,"BB");
    map.put(12,"CC");

    System.out.println(map);
} 


复制代码

1.3 Mapa de árbol

  • Cuando TreeMap almacena pares clave-valor, debe ordenarse de acuerdo con los pares clave-valor. TreeMap puede garantizar que todos los pares clave-valor estén en un estado ordenado.

  • La capa inferior de TreeSet utiliza una estructura de árbol rojo-negro para almacenar datos

  • La clasificación de la Clave del TreeMap:

    • Clasificación natural: todas las claves del TreeMap deben implementar la interfaz Comparable, y todas las claves deben ser objetos de la misma clase; de ​​lo contrario, se lanzará ClassCastException()
    • Clasificación personalizada: al crear un TreeMap, pase un objeto Comparator, que es responsable de clasificar todas las claves en el TreeMap. En este momento, no es necesario que Key of the Map implemente la interfaz Comparable.
  • TreeMap juzga los criterios para que dos claves sean iguales: dos claves devuelven 0 mediante el método compareTo() o el método compare().

1.4 tabla hash

  • Hashtable es una antigua clase de implementación de mapas, proporcionada por JDK1.0. A diferencia de HashMap, Hashtable es seguro para subprocesos.

  • El principio de implementación de Hashtable es el mismo que el de HashMap, y las funciones son las mismas. La capa inferior usa una estructura de tabla hash, la velocidad de consulta es rápida y se puede usar indistintamente en muchos casos

  • A diferencia de HashMap, Hashtable no permite valores nulos como clave y valor.

  • Al igual que HashMap, Hashtable no puede garantizar el orden de los pares clave-valor en él.

  • Hashtable juzga que dos claves son iguales y dos valores son iguales, lo cual es consistente con HashMap.

1.5 Propiedades

  • La clase de propiedades es una subclase de Hashtable, que se utiliza para procesar archivos de propiedades.

  • Dado que la clave y el valor en el archivo de propiedades son todos tipos de cadena, la clave y el valor en Propiedades son todos tipos de cadena

  • Al acceder a los datos, se recomienda utilizar  setProperty(String key,String value) métodos y  getProperty(String key) métodos.

Ejemplo de código:

//Properties:常用来处理配置文件。key和value都是String类型
public static void main(String[] args)  {
    FileInputStream fis = null;
    try {
        Properties pros = new Properties();

        fis = new FileInputStream("jdbc.properties");
        pros.load(fis);//加载流对应的文件

        String name = pros.getProperty("name");
        String password = pros.getProperty("password");

        System.out.println("name = " + name + ", password = " + password);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if(fis != null){
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

}


复制代码

2. Comprensión de la estructura de almacenamiento:

  • Key in Map: desordenado, no repetible, use la clave almacenada en Set ---> la clase donde se encuentra la clave debe reescribir equals() y hashCode() (tome HashMap como ejemplo)
  • Valor en el mapa: desordenado, repetible, use Collection para almacenar el valor ---> la clase donde se encuentra el valor debe reescribir equals()
  • Un par clave-valor: clave-valor constituye un objeto Entry.
  • Entrada en el mapa: desordenada, no repetible, use Establecer para almacenar la entrada

3. Métodos comunes

3.1 Operaciones de añadir, borrar, modificar:

  • Object put(Object key,Object value): agregue (o modifique) el valor-clave especificado al objeto de mapa actual
  • void putAll(Map m): almacena todos los pares clave-valor en m en el mapa actual
  • Object remove(Object key): elimina el par clave-valor de la clave especificada y devuelve el valor
  • void clear(): Borrar todos los datos en el mapa actual

Ejemplo de código:

@Test
public void test1() {
    Map map = new HashMap();
    //Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
    map.put("AA",123);
    map.put("ZZ",251);
    map.put("CC",110);
    map.put("RR",124);
    map.put("FF",662);
    System.out.println(map);//{AA=123, ZZ=251, CC=110, RR=124, FF=662}

    //Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
    map.put("ZZ",261);
    System.out.println(map);//{AA=123, ZZ=261, CC=110, RR=124, FF=662}

    //void putAll(Map m):将m中的所有key-value对存放到当前map中
    HashMap map1 = new HashMap();
    map1.put("GG",435);
    map1.put("DD",156);
    map.putAll(map1);
    System.out.println(map);//{AA=123, ZZ=261, CC=110, RR=124, FF=662, GG=435, DD=156}

    //Object remove(Object key):移除指定key的key-value对,并返回value
    Object value = map.remove("GG");
    System.out.println(value);//435
    System.out.println(map);//{AA=123, ZZ=261, CC=110, RR=124, FF=662, DD=156}

    //void clear():清空当前map中的所有数据
    map.clear();
    System.out.println(map.size());//0  与map = null操作不同
    System.out.println(map);//{}
}


复制代码

3.2 Funcionamiento de la consulta de elementos:

  • Object get(Object key): Obtener el valor correspondiente a la clave especificada
  • boolean containsKey(Object key): Si debe contener la clave especificada
  • boolean containsValue(Object value): Si contener el valor especificado
  • int size(): Devuelve el número de pares clave-valor en el mapa
  • boolean isEmpty(): determina si el mapa actual está vacío
  • boolean equals(Object obj): Determine si el mapa actual y el objeto de parámetro obj son iguales

Ejemplo de código:

@Test
public void test2() {
    Map map = new HashMap();
    map.put("AA", 123);
    map.put("ZZ", 251);
    map.put("CC", 110);
    map.put("RR", 124);
    map.put("FF", 662);
    System.out.println(map);//{AA=123, ZZ=251, CC=110, RR=124, FF=662}
    //Object get(Object key):获取指定key对应的value
    System.out.println(map.get("AA"));//123

    //boolean containsKey(Object key):是否包含指定的key
    System.out.println(map.containsKey("ZZ"));//true

    //boolean containsValue(Object value):是否包含指定的value
    System.out.println(map.containsValue(123));//true

    //int size():返回map中key-value对的个数
    System.out.println(map.size());//5

    //boolean isEmpty():判断当前map是否为空
    System.out.println(map.isEmpty());//false

    //boolean equals(Object obj):判断当前map和参数对象obj是否相等
    Map map1 = new HashMap();
    map1.put("AA", 123);
    map1.put("ZZ", 251);
    map1.put("CC", 110);
    map1.put("RR", 124);
    map1.put("FF", 662);
    System.out.println(map.equals(map1));//true
}


复制代码

3.3 Método de operación de metavista:

  • Set keySet(): Devuelve la colección Set compuesta por todas las claves.
  • Collection values(): Devuelve el conjunto de colección compuesto por todos los valores.
  • Set entrySet(): Devuelve la colección Set compuesta por todos los pares clave-valor

Ejemplo de código:

@Test
public void test3() {
    Map map = new HashMap();
    map.put("AA", 123);
    map.put("ZZ", 251);
    map.put("CC", 110);
    map.put("RR", 124);
    map.put("FF", 662);
    System.out.println(map);//{AA=123, ZZ=251, CC=110, RR=124, FF=662}
    //遍历所有的key集:Set keySet():返回所有key构成的Set集合
    Set set = map.keySet();
    Iterator iterator = set.iterator();
    while (iterator.hasNext()) {
        System.out.println(iterator.next());
    }
    System.out.println("--------------");
    //遍历所有的value集:Collection values():返回所有value构成的Collection集合
    Collection values = map.values();
    for (Object obj :
         values) {
        System.out.println(obj);
    }
    System.out.println("---------------");
    //Set entrySet():返回所有key-value对构成的Set集合
    Set entrySet = map.entrySet();
    Iterator iterator1 = entrySet.iterator();
    //方式一:
    while (iterator1.hasNext()) {
        Object obj = iterator1.next();
        //entrySet集合中的元素都是entry
        Map.Entry entry = (Map.Entry) obj;
        System.out.println(entry.getKey() + "-->" + entry.getValue());
    }
    System.out.println("--------------");

    //方式二:
    Set keySet = map.keySet();
    Iterator iterator2 = keySet.iterator();
    while (iterator2.hasNext()) {
        Object key = iterator2.next();
        Object value = map.get(key);
        System.out.println(key + "==" + value);
    }
}


复制代码

Resumen: Métodos comunes:

  • Añadir:put(Object key,Object value)
  • borrar:remove(Object key)
  • Revisar:put(Object key,Object value)
  • Preguntar:get(Object key)
  • longitud:size()
  • atravesar  :  keySet() // values()entrySet()

4. Descripción de la estructura de la memoria: (punto difícil)

4.1 Principio de implementación de HashMap en JDK 7.0:

4.1.1 Estructura de almacenamiento de HashMap:

JDK 7.0 y versiones anteriores: HashMap es una matriz + estructura de lista enlazada (método de lista enlazada de direcciones)

Después de la versión JDK 8.0: HashMap es una matriz + lista vinculada + implementación de árbol rojo-negro

4.1.2 Proceso de creación y adición de objetos:

HashMap map = new HashMap():

Después de la creación de instancias, el subyacente crea una matriz unidimensional de longitud 16  Entry[] table.

​ ...puede haber ejecutado varias opciones de venta...

map.put(key1,value1):

  • Primero, llame  hashCode() al valor hash de clave 1 de cálculo de la clase a la que pertenece key1.Después de que un determinado algoritmo calcule el valor hash, se obtiene la ubicación de almacenamiento en la matriz Entry.
  • Si los datos en esta posición están vacíos, key1-value1 se agrega correctamente en este momento. ---- Situación 1
  • Si los datos en esta ubicación no están vacíos (lo que significa que hay uno o más datos (en forma de lista enlazada) en esta ubicación), compare key1 con el valor hash de uno o más datos existentes:
    • Si el valor hash de key1 es diferente del valor hash de los datos existentes, key1-value1 se agrega correctamente. ---- Situación 2
    • Si el valor hash de key1 es el mismo que el valor hash de un dato existente (key2-value2), continúe con la comparación: llame al método equals (key2) de la clase donde se encuentra key1 y compare:
      • Si  equals() devuelve falso: key1-value1 se agrega con éxito en este momento. ---- Situación 3
      • Si es  equals() verdadero: reemplace valor2 con valor1.

Complemento: Con respecto al caso 2 y al caso 3: En este momento, clave1-valor1 y los datos originales se almacenan en forma de lista enlazada.

En el proceso de adición continua, estará involucrado el problema de la expansión de la capacidad, cuando se exceda el valor crítico (y la ubicación a almacenar no esté vacía), la capacidad se expandirá. El método de expansión predeterminado: expanda la capacidad al doble de la capacidad original y copie los datos originales.

4.1.3 Expansión de HashMap

Cuando hay más y más elementos en HashMap, la probabilidad de conflictos de hash aumenta cada vez más, porque la longitud de la matriz es fija. Por lo tanto, para mejorar la eficiencia de la consulta, es necesario expandir la matriz HashMap, y después de expandir la matriz HashMap, los datos en la matriz original deben volver a calcular su posición en la nueva matriz y colocarlos. Esto es cambiar el tamaño.

4.1.4 Tiempo de expansión de HashMap

Cuando el número de elementos en HashMap excede el tamaño de la matriz (la longitud total de la matriz, no el número en la matriz) * factor de carga, la matriz se expandirá. El valor predeterminado de factor de carga () es 0.75, que es un valor de compromiso DEFAULT_LOAD_ FACTOR. Es decir, por defecto, el tamaño del arreglo ( DEFAULT INITIAL CAPACITY) es 16, entonces cuando el número de elementos en el HashMap excede 16 * 0.75=12 (este valor es el valor umbral en el código, también llamado valor crítico), el matriz El tamaño se expande a 2 * 16 = 32, es decir, se duplica, y luego vuelve a calcular la posición de cada elemento en la matriz, y esta es una operación que consume mucho rendimiento, por lo que si ya hemos predicho la cantidad de elementos en el HashMap, luego preestablecer el número de elementos puede mejorar efectivamente el rendimiento de HashMap.

4.2 El principio de implementación subyacente de HashMap en JDK 8.0:

4.2.1 Estructura de almacenamiento de HashMap:

La estructura de almacenamiento interno de HashMap es en realidad una combinación de matriz + lista vinculada + árbol rojo-negro.

4.2.2 El proceso de agregar elementos a HashMap:

Al crear una instancia de HashMap, initialCapacity y loadFactor se inicializarán. Al colocar el primer par de relaciones de mapeo, el sistema creará una matriz de nodos con una longitud de initialCapacity. Esta longitud se denomina capacidad en la tabla hash. En esta ubicación donde se encuentran los elementos se puede almacenar en la matriz se denomina "depósito". Cada depósito tiene su propio índice, y el sistema puede encontrar rápidamente elementos en el depósito en función del índice.

Cada cubo almacena un elemento, es decir, un objeto Nodo, pero cada objeto Noe puede llevar una variable de referencia al lado para apuntar al siguiente elemento, por lo tanto, en un cubo es posible generar una cadena Nodo. También puede ser un objeto TreeNode, cada objeto Tree node puede tener dos nodos de hoja a la izquierda y a la derecha, por lo tanto, en un cubo, es posible generar un árbol TreeNode. El elemento recién agregado se usa como el último de la lista enlazada, o el nodo de hoja del árbol.

4.2.3 El mecanismo de expansión de HashMap:

  • Cuando el número de objetos en una de las cadenas en HashMapl no llega a 8, es el mismo que el método de expansión antes de JDK 7.0.
  • Cuando el número de objetos en una de las cadenas en HashMapl llegue a 8, si la capacidad no llega a 64 en este momento, entonces HashMap expandirá la capacidad primero. Si ha llegado a 64, entonces la cadena se convertirá en un árbol, y el el tipo de nodo está determinado por El nodo se convierte en el tipo de nodo de árbol. Por supuesto, si se considera que el número de nodos del árbol es inferior a 6 en el siguiente método de cambio de tamaño después de eliminar la relación de correlación, el árbol se convertirá de nuevo en una lista enlazada.

4.2.4 Cambios en la parte inferior de HashMap entre JDK 8.0 y JDK 7.0:

  1. new HashMap(): La capa inferior no creó una matriz de longitud 16

  2. La matriz subyacente de JDK 8.0 es: Node[], no Entry[]

  3. Cuando se llama al método put() por primera vez, la capa subyacente crea una matriz con una longitud de 16

  4. La estructura subyacente de JDK 7.0 es solo: matriz + lista enlazada. La estructura subyacente en JDK 8.0: matriz + lista enlazada + árbol rojo-negro.

    • Al formar una lista enlazada, es hacia arriba y hacia abajo (jdk7: los elementos nuevos apuntan a elementos antiguos. jdk8: los elementos antiguos apuntan a elementos nuevos)
    • Cuando el número de elementos en una cierta posición de índice de la matriz en forma de lista enlazada es > 8 y la longitud de la matriz actual es > 64, todos los datos en esta posición de índice se almacenarán en un árbol rojo-negro en cambio.

4.3 Descripción de las propiedades de las propiedades típicas de la capa inferior de HashMap:

  • DEFAULT_INITIAL_CAPACITY : La capacidad predeterminada de HashMap, 16
  • DEFAULT_LOAD_FACTOR: Factor de carga predeterminado para HashMap: 0,75
  • threshold: Valor crítico de expansión, = capacidad * factor de llenado: 16 * 0,75 => 12
  • TREEIFY_THRESHOLD: La longitud de la lista vinculada en el Cubo es mayor que el valor predeterminado y se convierte en un árbol rojo-negro: introducido por JDK 8.0
  • MIN_TREEIFY_CAPACITY: La capacidad mínima de la tabla hash cuando el Nodo en el depósito está en árbol: 64

4.4 El principio de implementación subyacente de LinkedHashMap

  • La estructura subyacente de LinkedHashMap es la misma que la de HashMap, porque LinkedHashMap hereda de HashMap.
  • La diferencia es que LinkedHashMap proporciona Entry inside, reemplazando Node en HashMap.
  • Similar a Linkedhash Set, LinkedHashMap puede mantener el orden de iteración de Map: el orden de iteración es consistente con el orden de inserción de pares clave-valor

Código fuente del nodo de clase interna en HashMap:

static class Node<K,V> implements Map.Entry<K,V>{
    final int hash;
    final K key;
    V value;
    Node<K,V> next;
}


复制代码

Código fuente de entrada de clase interna en LinkedHashM:

static class Entry<K,V> extends HashMap.Node<K,V> {
    Entry<K,V> before, after;//能够记录添加的元素的先后顺序
    Entry(int hash, K key, V value, Node<K,V> next) {
        super(hash, key, value, next);
    }
}


复制代码

5. Uso de TreeMap

Agregue clave-valor a TreeMap, lo que requiere que la clave debe ser creada por la misma clase. Los objetos deben ordenarse de acuerdo con la clave: clasificación natural, clasificación personalizada

Ejemplo de código:

//自然排序
@Test
public void test() {
    TreeMap map = new TreeMap();
    User u1 = new User("Tom", 23);
    User u2 = new User("Jarry", 18);
    User u3 = new User("Bruce", 56);
    User u4 = new User("Davie", 23);

    map.put(u1, 98);
    map.put(u2, 16);
    map.put(u3, 92);
    map.put(u4, 100);

    Set entrySet = map.entrySet();
    Iterator iterator = entrySet.iterator();
    while (iterator.hasNext()) {
        Object obj = iterator.next();
        Map.Entry entry = (Map.Entry) obj;
        System.out.println(entry.getKey() + "=" + entry.getValue());
    }
}

//定制排序:按照年龄大小排
@Test
public void test2() {
    TreeMap map = new TreeMap(new Comparator() {
        @Override
        public int compare(Object o1, Object o2) {
            if (o1 instanceof User && o2 instanceof User) {
                User u1 = (User) o1;
                User u2 = (User) o2;
                return Integer.compare(u1.getAge(), u2.getAge());
            }
            throw new RuntimeException("输入数据类型错误");
        }
    });
    User u1 = new User("Tom", 23);
    User u2 = new User("Jarry", 18);
    User u3 = new User("Bruce", 56);
    User u4 = new User("Davie", 23);

    map.put(u1, 98);
    map.put(u2, 16);
    map.put(u3, 92);
    map.put(u4, 100);

    Set entrySet = map.entrySet();
    Iterator iterator = entrySet.iterator();
    while (iterator.hasNext()) {
        Object obj = iterator.next();
        Map.Entry entry = (Map.Entry) obj;
        System.out.println(entry.getKey() + "=" + entry.getValue());
    }
}


复制代码

6. Use Propiedades para leer el archivo de configuración

Ejemplo de código:

//Properties:常用来处理配置文件。key和value都是String类型
public static void main(String[] args)  {
    FileInputStream fis = null;
    try {
        Properties pros = new Properties();

        fis = new FileInputStream("jdbc.properties");
        pros.load(fis);//加载流对应的文件

        String name = pros.getProperty("name");
        String password = pros.getProperty("password");

        System.out.println("name = " + name + ", password = " + password);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if(fis != null){
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

}


复制代码

7. Preguntas de la entrevista

  1. ¿El principio de implementación subyacente de HashMap?
  2. ¿Similitudes y diferencias entre HashMap y Hashtable?
  3. ¿Similitudes y diferencias entre CurrentHashMap y Hashtable?
  4. ¿El tamaño del valor del factor de carga, el impacto en el HashMap?
    • El tamaño del factor de carga determina la densidad de datos del HashMap.
    • Cuanto mayor sea el factor de carga, mayor será la densidad, mayor será la probabilidad de colisión y más fácil será el crecimiento de la lista enlazada en la matriz, lo que dará como resultado un aumento en el número de comparaciones durante la consulta o la inserción y una degradación del rendimiento.
    • Cuanto menor sea el factor de carga, más fácil será desencadenar la expansión y menor será la densidad de datos, lo que significa que la probabilidad de colisión es menor, la lista vinculada en la matriz es más corta y el número de comparaciones durante la consulta y la inserción es menor. más pequeño, y el rendimiento será mayor. Pero desperdiciará un cierto espacio de contenido. Además, la expansión frecuente también afectará el rendimiento. Se recomienda inicializar y preestablecer un espacio más grande
    • De acuerdo con la experiencia de referencia e investigación de otros idiomas, se considerará establecer el factor de carga entre 0,7 y 0,75. En este momento, la longitud de recuperación promedio es casi constante.

Siete, el uso de herramientas de colección.

1. Función:

Colecciones es una clase de herramienta para manipular colecciones como Set, Lit y ​​Map

Colecciones proporciona una serie de métodos estáticos para ordenar, consultar y modificar elementos de colección, y también proporciona métodos para establecer objetos de colección inmutables y realizar el control de sincronización en los objetos de colección.

2. Métodos comunes:

2.1 Operación de clasificación

  • reverse(List): Invertir el orden de los elementos en la Lista
  • shuffle(List): ordenar aleatoriamente los elementos de la colección List
  • sort(List): ordena los elementos de la colección de listas especificada en orden ascendente de acuerdo con el orden natural de los elementos
  • sort(List,Comparator): Ordene los elementos de la colección de la Lista de acuerdo con el orden generado por el Comparador especificado
  • swap(List,int, int): Intercambia el elemento en i y el elemento en j en la colección de listas especificada

Ejemplo de código:

@Test
public void test1() {
    List list = new ArrayList();
    list.add(123);
    list.add(43);
    list.add(765);
    list.add(-97);
    list.add(0);
    System.out.println(list);//[123, 43, 765, -97, 0]

    //reverse(List):反转 List 中元素的顺序
    Collections.reverse(list);
    System.out.println(list);//[0, -97, 765, 43, 123]

    //shuffle(List):对 List 集合元素进行随机排序
    Collections.shuffle(list);
    System.out.println(list);//[765, -97, 123, 0, 43]

    //sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
    Collections.sort(list);
    System.out.println(list);//[-97, 0, 43, 123, 765]

    //swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
    Collections.swap(list,1,4);
    System.out.println(list);//[-97, 765, 43, 123, 0]
}


复制代码

2.2 Buscar y reemplazar

  • Object max(Collection): Devuelve el elemento más grande de la colección dada según el orden natural de los elementos
  • Object max(Collection,Comparator): Según el orden especificado por Comparator, devuelve el elemento más grande de la colección dada
  • Object min(Collection)
  • Object min(Collection,Comparator)
  • int frequency(Collection,Object): Devuelve el número de ocurrencias del elemento especificado en la colección especificada
  • void copy(List dest,List src): Copiar el contenido de src a dest
  • boolean replaceAll(List list,Object oldVal,Object newVal): Reemplace todos los valores antiguos del objeto Lista con valores nuevos

Ejemplo de código:

@Test
public void test2(){
    List list = new ArrayList();
    list.add(123);
    list.add(123);
    list.add(123);
    list.add(43);
    list.add(765);
    list.add(-97);
    list.add(0);
    System.out.println(list);//[123, 43, 765, -97, 0]
    //Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
    Comparable max = Collections.max(list);
    System.out.println(max);//765

    //Object min(Collection)
    Comparable min = Collections.min(list);
    System.out.println(min);//-97

    //int frequency(Collection,Object):返回指定集合中指定元素的出现次数
    int frequency = Collections.frequency(list,123);
    System.out.println(frequency);//3

    //void copy(List dest,List src):将src中的内容复制到dest中
    List dest = Arrays.asList(new Object[list.size()]);
    System.out.println(dest.size());//7
    Collections.copy(dest,list);
    System.out.println(dest);//[123, 123, 123, 43, 765, -97, 0]
    //boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
}


复制代码

2.3 Control síncrono

La clase Collections proporciona varios  synchronizedXxx() métodos, que pueden envolver la colección especificada en una colección sincronizada con subprocesos, para resolver el problema de seguridad de los subprocesos cuando varios subprocesos acceden a la colección al mismo tiempo.

Ejemplo de código:

@Test
public void test3() {
    List list = new ArrayList();
    list.add(123);
    list.add(123);
    list.add(123);
    list.add(43);
    list.add(765);
    list.add(-97);
    list.add(0);
    System.out.println(list);//[123, 43, 765, -97, 0]
    //返回的list1即为线程安全的List
    List list1 = Collections.synchronizedList(list);
    System.out.println(list1);//[123, 123, 123, 43, 765, -97, 0]
}


复制代码

8. Breve descripción de la estructura de datos

Está previsto abrir una serie en el futuro para hablar de la estructura de datos.

1. Descripción general de la estructura de datos

Estructura de datos (La estructura de datos es una disciplina estrechamente relacionada con el hardware y el software de la computadora. Su enfoque de investigación es cómo organizar y almacenar datos en la computadora y usarlos de manera eficiente en el campo de la programación de computadoras. El contenido involucrado Incluye: relación lógica de datos , estructura de almacenamiento de datos, algoritmo de clasificación (Algorithm), búsqueda (o búsqueda), etc.

2. Comprensión de estructuras de datos y algoritmos.

Si el programa puede completar la tarea predeterminada de manera rápida y eficiente depende de si la estructura de datos se selecciona correctamente, y si el programa puede resolver el problema de manera clara y correcta depende del algoritmo.

Entonces todos piensan: "Algoritmos + Estructuras de datos = Programas" (de: Nicklaus Wirth, padre de Pascal)

Resumen: Los algoritmos están diseñados para resolver problemas prácticos, y las estructuras de datos son los portadores de problemas con los que deben lidiar los algoritmos.

3. Objeto de investigación de la estructura de datos

3.1 Estructura lógica entre datos

establecer estructura

Uno a uno: estructura lineal

Uno a muchos: estructura de árbol

Muchos a muchos: estructura gráfica

3.2 Estructura de almacenamiento de datos:

Diagrama de árbol de lista lineal (lista de secuencias, lista enlazada, pila, cola)

Explicación: Se acostumbra considerar las listas secuenciales y las listas enlazadas como estructuras de datos básicas (o estructuras de datos reales). Se acostumbra considerar las pilas, las colas, los árboles y los gráficos como tipos de datos abstractos, denominados ADT.

4. Mapa mental:

Dirección de descarga del mapa mental: gitee.com/realbruce/b…

Estructuras de datos y algoritmos:


 

 

Supongo que te gusta

Origin blog.csdn.net/SFalS/article/details/127332202
Recomendado
Clasificación