Colecciones Java basic 16 (ArrayList, LinkedList, HashSet, HashMap)

¡Como tú que amas la programación!
Aprenda los cursos prácticos de SpringBoot https://edu.csdn.net/course/detail/31433
Aprenda los cursos de introducción a SpringCloud https://edu.csdn.net/course/detail/31451


Prefacio

Cuando guardamos una gran cantidad de datos, primero pensamos en matrices. Pero la longitud de la matriz es fija y existe un problema si guarda una cantidad indeterminada de datos.
Este artículo lo llevará a comprender la arquitectura del marco de recopilación de Java, comprender la diferencia entre las interfaces List, Set y Map, y centrarse en el uso, la estructura de datos y los principios de implementación de ArrayList, LinkedList, HashSet y HashMap.

Sistema de marco colectivo

Inserte la descripción de la imagen aquí

Características de la interfaz:

  • La interfaz de Colección
    define los métodos generales de la colección, tales como: agregar, eliminar, número de colecciones
  • La interfaz de lista
    se puede ordenar y se pueden agregar datos duplicados

  • No se puede acceder a la interfaz configurada por separado y los datos no se pueden repetir

  • Pares clave-valor de interfaz de mapa , a los que se accede mediante claves

Los principales métodos de la interfaz de Colección:

método Introducción
suma booleana (objeto obj) Agregar un objeto
boolean addAll (Colección c) Agregar todos los objetos de otra colección
booleano eliminar (Objeto obj) Eliminar un objeto
boolean removeAll (Colección c) Eliminar todos los objetos de una colección
vacío claro () Eliminar todos los objetos
int tamaño () Número de objetos guardados
booleano contiene (Objeto obj) Determinar si existe un objeto
Objeto [] toArray () Devuelve los objetos de la colección como una matriz

Interfaz de lista

Puede operar por subíndice, puede agregar datos duplicados, puede ordenar los
métodos principales:

método Introducción
añadir vacío (índice int, objeto obj) Agregar un objeto en una ubicación determinada
Obtener objeto (índice int) Devolver un objeto en una posición determinada
Objeto eliminar (índice int) Eliminar un objeto en una posición determinada
Conjunto de objetos (índice int, objeto obj) Reemplazar un objeto en una posición determinada
Lista subLista (int inicio, int fin) Interceptar parte de la colección
int indexOf (Objeto) Devuelve la posición del objeto en la colección.
booleano contiene (Objeto obj) Determinar si existe un objeto

Clase ArrayList

La clase ArrayList es la clase de implementación de la interfaz List y es una colección que se usa mucho durante el desarrollo.
La estructura de datos de ArrayList es:
matriz unidimensional

Las ventajas y desventajas de ArrayList:

  • Ventajas: velocidad de acceso rápida, espacio de almacenamiento continuo, posicionamiento directo a través de subíndices
  • Desventajas: rendimiento deficiente de eliminación e inserción, necesidad de mover muchos datos hacia adelante o hacia atrás

Método de creación:

ArrayList arrayList = new ArrayList();

o

ArrayList arrayList = new ArrayList(默认容量);

agregando datos:

add(Object 数据)				添加数据到末尾,参数是Object类型,可以添加任何类型的数据。
add(int 下标,Object 数据)	在特定位置添加数据
addAll(Collection 集合)		添加一个集合中所有数据

cambiar los datos:

set(int 下标,Object 数据)		修改特定位置上数据

Datos de acceso:

get(下标)				返回某个下标上的数据

Numero de datos:

int size()				数据个数

borrar datos:

remove(int 下标)			删除特定位置上的数据
clear()					删除所有数据

Atraviesa la colección:
foreach loop

for(Object obj : list){
	System.out.println("集合中的数据:"+obj);
}

Ordinario para bucle

int size = list.size();
for(int i = 0;i < size;i++){
	Object obj = list.get(i);
	System.out.println("集合中的数据:"+obj);
}

Análisis de código fuente ArrayList:
¿cómo guardar datos? Matriz unidimensional de tipo de objeto

transient Object[] elementData;

¿Cuál es la longitud inicial de la matriz? 10

private static final int DEFAULT_CAPACITY = 10;

¿Cómo se expande ArrayList de forma dinámica? Si el número de datos excede la capacidad original, la capacidad se amplía a 1,5 veces la capacidad original y luego los datos se copian en la nueva matriz.

private void grow(int minCapacity) {
     // overflow-conscious code
     int oldCapacity = elementData.length;
     int newCapacity = oldCapacity + (oldCapacity >> 1); //扩容1.5倍
     if (newCapacity - minCapacity < 0)
         newCapacity = minCapacity;
     if (newCapacity - MAX_ARRAY_SIZE > 0)
         newCapacity = hugeCapacity(minCapacity);
     // minCapacity is usually close to size, so this is a win:
     elementData = Arrays.copyOf(elementData, newCapacity); //复制数据到新数组中
}

Colección de vectores

La colección Vector es similar a ArrayList:

  1. Las estructuras de datos son todas matrices unidimensionales
  2. El método es exactamente el mismo

diferencia:

  1. ArrayList no es seguro para subprocesos, Vector es seguro para subprocesos
  2. El rendimiento de ArrayList es mayor

Colección genérica

¿Qué podría estar mal con el siguiente código?

List list = new ArrayList();
list.add(100);
list.add("123");
int n = (int)list.get(1); //存在类型转换的错误
String s = (String)list.get(0); //存在类型转换的错误

Para las colecciones no genéricas, no hay restricción en el tipo de datos agregados Cuando los datos se extraen para la conversión de tipos, existe un problema de incompatibilidad de tipos.

El uso de colecciones genéricas puede resolver este problema.

Método de creación:

ArrayList<类型> arrayList = new ArrayList<类型>();

P.ej:

ArrayList<String> arrayList = new ArrayList<String>();
ArrayList<Integer> arrayList = new ArrayList<Integer>();
后面的类型可以省略
ArrayList<Integer> arrayList = new ArrayList<>(); 

ventaja:

  1. Solo se puede agregar un tipo de datos, no es fácil cometer errores
  2. Sin conversión de tipo, mejora el rendimiento
ArrayList<Person> arrList = new ArrayList<Person>();
arrList.add(new Person("张三",20));
arrList.add(new Person("张大三",21));
arrList.add(new Person("张小三",23));
arrList.add(new Person("张三三",26));
arrList.add(100);  //编译错误,不允许添加其他类型
//读取Person对象
Person person = arrList.get(3);
person.hello();
//删除
arrList.remove(0);
//遍历
for(Person per : arrList){
	per.hello();
}

Lista enlazada

La estructura de datos de LinkedList es:
lista doblemente enlazada
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí

Las ventajas y desventajas de LinkedList:

  • Ventajas: rápida eliminación y velocidad de inserción, solo es necesario modificar los puntos frontal y posterior, no es necesario mover datos
  • Desventajas: La velocidad de acceso es lenta, debe ser hacia adelante y hacia atrás a su vez, y la eficiencia es baja.

Método LinkedList

método Introducción
void addFirst (objeto obj) Agrega el objeto en la primera posición
void addLast (Objeto obj) Agregar un objeto en la última posición
Objeto removeFirst () Eliminar el objeto en la primera posición
Objeto removeLast () Eliminar el objeto en la última posición
Objeto getFirst () Coloca el objeto en la primera posición
Objeto getLast () Obtener la última posición del objeto
empuje vacío (objeto obj) Apilar, primero en entrar, último en salir
Objeto emergente () Fuera de la pila, primero en entrar, último en salir

Exploración del código fuente de 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;
    }
}

Insertar elemento

//在succ节点前,插入新节点
void linkBefore(E e, Node<E> succ) {
    final Node<E> pred = succ.prev;  	//succ前一个节点
    //创建新节点,prev指向succ前面节点,next指向succ
    final Node<E> newNode = new Node<>(pred, e, succ); 
    succ.prev = newNode;     		//succ的prev指向新节点
    if (pred == null)
        first = newNode;  		 		//前面没有节点,新节点就是首节点
    else
        pred.next = newNode;  		//否则succ前面节点的next指向新节点
    size++;									//数量加1
    modCount++;
}

Insertar elemento

//删除x节点
E unlink(Node<E> x) {
     final E element = x.item;
     final Node<E> next = x.next;
     final Node<E> prev = x.prev;
     if (prev == null) {       //x前面节点的next指向x节点的后面节点
         first = next;
     } else {
         prev.next = next;
         x.prev = null;
     }
     if (next == null) {       //x后面节点的prev指向x节点的前面节点
         last = prev;
     } else {
         next.prev = prev;
         x.next = null;
     }
     x.item = null;
     size--;
     modCount++;
     return element;
 }

Establecer interfaz

El conjunto no puede agregar datos duplicados y no se puede acceder a los datos internos por separado

Las clases de implementación de uso común de la interfaz Set son:

  • Conjunto desordenado HashSet
  • TreeSet ordenará automáticamente el conjunto
  • LinkedHashSet puede mantener el conjunto de agregar orden

HashSet

Desordenada, la ubicación de almacenamiento se calcula mediante el algoritmo hash
. Los datos agregados a la colección deben implementar el hashCode y los métodos equals. La
implementación inferior es HashMap, y los datos se almacenan en la clave de HashMap

public class HashSet<E> extends AbstractSet<E>
{
   
    private transient HashMap<E,Object> map;
	private static final Object PRESENT = new Object();
    public HashSet() {
        map = new HashMap<>();
    }
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
    ...
}

Interfaz de mapa

Datos de acceso a la estructura de pares clave-valor, fáciles de encontrar y eficientes.
Métodos comunes:

método Introducción
V poner (tecla K, valor V) Almacenar el par "clave-valor" especificado en el mapa
V get (clave de objeto) Devuelve el valor asignado por la clave especificada
V eliminar (tecla de objeto) Eliminar este par "clave-valor" del mapa de acuerdo con la clave especificada
boolean containsKey (clave de objeto) Determinar si este mapa contiene la clave especificada
boolean containsValue (valor del objeto) Determine si este mapa contiene el valor especificado
boolean isEmpty () Determinar si hay elementos en este mapa
int tamaño () Obtener el número de pares "clave-valor" en el mapa
vacío claro () Borrar todos los pares "clave-valor" en el mapa
Establecer keySet () Devuelve la colección de claves contenidas en este mapa
Valores de colección () Devuelve la colección de valores en este mapa.

HashMap

El acceso a los datos en forma de tabla hash utiliza muchas colecciones.
Método de creación:

HashMap<键类型,值类型> hashmap = new HashMap<>();

Instrucciones:

//创建HashMap保存人的对象
HashMap<String,Person> map = new HashMap<String,Person>();
Person person1 = new Person("张三",20);
Person person2 = new Person("李四",22);
Person person3 = new Person("王五",20);
//添加人到集合中
map.put(person1.getName(), person1);
map.put(person2.getName(), person2);
map.put(person3.getName(), person3);
//通过键访问值
map.get("张三").hello();
//删除
map.remove("李四");
//添加重复的键,将新的值覆盖原来的值
map.put("李四", new Person("李四",33));
System.out.println("长度:" + map.size());
//遍历所有的键
for(String key : map.keySet()){
	System.out.println("键: " + key);
}
//遍历所有的值
for(Person per : map.values()){
	per.hello();
}
//遍历所有的键和值
for(String key : map.keySet()){
	System.out.println("键: " + key);
	map.get(key).hello();
}

Características de HashMap

  1. Si se agrega una clave duplicada, el valor agregado posteriormente reemplazará el valor anterior.
  2. Los datos se almacenan en un algoritmo hash, no en el orden de adición
  3. La clave agregada debe implementar los métodos hashCode y equals

Estructura de datos de HashMap
Matriz unidimensional + lista enlazada individualmente + árbol rojo-negro
Inserte la descripción de la imagen aquí
Proceso HashMap de guardar datos

  1. Al agregar datos de pares clave-valor, primero se llama al método hashCode de la clave para calcular el subíndice de matriz
  2. Si los datos del subíndice están vacíos, guárdelos directamente
  3. Si hay datos en el subíndice, los iguales de la clave llamada se comparan con la clave en esa posición.
  4. Si es igual a devuelve verdadero, los datos antiguos se sobrescribirán con los nuevos.
  5. Si es igual a devuelve falso, coloque los datos nuevos detrás de los datos antiguos para formar una lista vinculada
  6. Cuando la longitud de la lista vinculada excede 8, se convierte automáticamente en un árbol rojo-negro (optimización de java8)

Análisis de código fuente HashMap

//添加数据
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
  Node<K,V>[] tab; Node<K,V> p; int n, i;
  if ((tab = table) == null || (n = tab.length) == 0)
      n = (tab = resize()).length;                  // 获得数组长度
  if ((p = tab[i = (n - 1) & hash]) == null)     //hashCode对数组长度-1取模获得下标i
      tab[i] = newNode(hash, key, value, null);   //该位置为空就直接添加数据
  else {
      Node<K,V> e; K k;
      if (p.hash == hash &&
          ((k = p.key) == key || (key != null && key.equals(k))))  //不为空就调用equals比较键
          e = p;																				 //键相同就赋值给e,后面直接覆盖value
      else if (p instanceof TreeNode)
          e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
      else {
          for (int binCount = 0; ; ++binCount) {
              if ((e = p.next) == null) {
                  p.next = newNode(hash, key, value, null);  //键不相同就放到后面,形成链表
                  if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st    
                      treeifyBin(tab, hash);	   //链表长度超过8,转换为红黑树
                  break;
              }
              if (e.hash == hash &&
                  ((k = e.key) == key || (key != null && key.equals(k))))
                  break;
              p = e;
          }
      }
      if (e != null) { // existing mapping for key
          V oldValue = e.value;
          if (!onlyIfAbsent || oldValue == null)
              e.value = value;        //覆盖旧的value
          afterNodeAccess(e);
          return oldValue;
      }
  }
  ++modCount;
  if (++size > threshold)
      resize();
  afterNodeInsertion(evict);
  return null;
}

Tabla de picadillo

El uso y la estructura de Hashtable y HashMap son los mismos.
Diferencias:

  1. HashMap no es seguro para subprocesos, Hashtable es seguro para subprocesos
  2. HashMap puede agregar claves y valores nulos, Hashtable no puede agregar claves y valores nulos

TreeMap

特点:添加数据后,会自动对键进行排序
数据结构:红黑树
Inserte la descripción de la imagen aquí
使用时需要注意:

  1. 键必须实现Comparable接口
  2. 键如果和已存在的键相等,TreeMap就放弃添加

LinkedHashMap

继承于HashMap,通过额外的链表保留键的添加顺序。
Inserte la descripción de la imagen aquí

如何选择集合

在开发过程中,需要根据实际业务场景,结合集合的特点选择集合

  • 可以排序,可以添加重复数据,可以随机访问 ----- List
    • 对数据访问要求高 ----- ArrayList
    • 对插入和删除要求高 ----- LinkedList
  • 不能添加重复的数据,不需要随机访问 ------ Set
    • 没有顺序 ----- HashSet
    • 可以进行排序 ----- TreeSet
    • 保留添加顺序 ----- LinkedHashSet
  • 可以进行快速查找 ,以键值对保存------ Map
    • 键没有顺序 ----- HashMap
    • 键可以排序 ----- TreeMap
    • 键保留添加顺序 ----- LinkedHashMap

结束

集合是Java的重点内容,尤其是ArrayList和HashMap这两个集合应用非常广泛,是否掌握了就通过作业检查了。

  1. 定义歌曲类,属性:歌曲名、歌手名、播放时长(int 类型),定义play方法显示歌曲信息。
    1、添加10首歌到ArrayList集合中
    2、遍历所有的歌曲,显示歌曲信息
    3、输入歌曲名,在集合中查找该歌曲
    4、输入整数索引,删除该位置的歌曲
    5、找出播放时间最长的歌曲
    6、将所有歌曲复制到LinkedList集合中
  2. Cambie la colección a HashMap, use el nombre de la canción como clave y la canción como valor.
    1. Agregue 10 canciones a la colección.
    2. Recorra todas las canciones y muestre la información de la canción.
    3. Ingrese el nombre de la canción y busque el canción en la colección.
    4. Ingrese el nombre de la canción, elimine la canción

Si necesita aprender otros conocimientos de Java, haga clic aquí Conocimiento ultra detallado de Java Resumen

Supongo que te gusta

Origin blog.csdn.net/u013343114/article/details/112602465
Recomendado
Clasificación