Java collection framework (4) -Interfaz de mapa

Primero, la estructura de la clase de implementación del Mapa

Mapa: datos de doble columna, almacenamiento de datos con pares clave-valor

1. HashMap: como la principal clase de implementación de Map, el subproceso es inseguro, de alta eficiencia y almacena la clave y el valor nulos
2. LinkedHashMap: para garantizar que al atravesar el elemento del mapa, la
razón transversal se pueda implementar en el orden de adición : en la parte inferior de HashMap Sobre la base de la estructura anterior, se agregan un par de punteros para señalar el elemento anterior y el siguiente elemento. Para las operaciones transversales frecuentes, la eficiencia de este tipo de ejecución es mayor que HashMap
3. TreeMap: asegúrese de que los pares clave-valor agregados estén ordenados para lograr la clasificación Atravesar. De acuerdo con la clasificación natural o personalizada de las claves, la parte inferior utiliza árboles rojos y negros Características: ordenada, alta eficiencia de consulta
4. Hashtable: existía en la era jdk1.0, seguridad de subprocesos, baja eficiencia, no puede almacenar claves nulas y valor
5 Propiedades: una subclase de Hashtable, comúnmente utilizada para procesar archivos de configuración. Tanto la clave como el valor son
la capa inferior del tipo de cadena HashMap: matriz + lista vinculada (jdk7) // matriz + lista vinculada + árbol negro rojo (jdk8)
Inserte la descripción de la imagen aquí

En segundo lugar, la comprensión de la estructura del mapa (HashMap)

1. La clave en el mapa: no ordenada, no repetible, use set para almacenar todas las claves-> la clase donde se encuentra la clave debe anular equals () y hashCode ()
2. El valor en el mapa: no ordenado, puede Repita, use la colección para almacenar todos los valores -----------> la clase donde se va a reescribir el valor es igual a ()
3, un par clave-valor: clave-valor constituye un objeto de entrada (entrada en Mapa : Desordenado, no repetible, use set para almacenar todas las entradas)

Inserte la descripción de la imagen aquí

3. ¿El principio de implementación subyacente de HashMap? Tome jdk7 como ejemplo:

HashMap map = new HashMap ();
Después de la creación de instancias, la capa inferior crea una tabla de entrada de matriz unidimensional [] de longitud 16.

... Para realizar múltiples métodos de venta ...

map.put (clave, valor);

Primero, llame al hashCode () de la clase donde se encuentra la clave para calcular el valor hash de la clave. Después de cierto algoritmo, el valor hash se almacena en la matriz de entrada.

Si los datos en esta ubicación están vacíos, el valor-clave se agrega con éxito. - Éxito 1

Si los datos en esta ubicación no están vacíos (existe uno o más datos en esta ubicación y existe en forma de una lista vinculada), compare el valor hash de la clave y el uno o más datos existentes:

Si el valor hash de la clave es diferente del valor hash de los datos existentes, entonces el valor clave se agrega con éxito 2

Si el valor hash de la clave es el mismo que el valor hash de uno de los datos existentes (clave1-valor1), continúe comparando: llame al método igual (clave1) de la clase donde se encuentra la clave
para la comparación:
si devuelve falso: el valor clave se agrega en este momento Éxito - Éxito 3
Si devuelve verdadero: reemplace valor1 con la misma clave1 con valor

2 y 3: en este momento, el valor clave y los datos originales se almacenan en forma de una lista vinculada.

En el proceso de adición continua, la expansión de la capacidad estará involucrada. Cuando se excede el valor crítico y la posición actual no está vacía, el método predeterminado de expansión de la capacidad es duplicar la capacidad original y copiar los datos originales.

Jdk8 y jdk7 son diferentes en la implementación de la capa inferior:
1. new HashMap (): la capa inferior no crea una matriz de longitud 16.
2. Cuando la matriz en la parte inferior de jdk8 es Nodo [], ya no es Entrada [] (Nodo <K, V> [] table;)
3. Cuando se llama al método put por primera vez, la capa inferior crea una matriz de 16
put V pública ( K key, V value) {
// Llame a hash para crear un array
return putVal (hash (key), key, value, false, true);
}
4. La estructura subyacente de jdk7 es: array + lista vinculada jdk8 La estructura subyacente: array + Lista vinculada + árbol rojo-negro
4.1. Al formar una lista vinculada, vaya hacia arriba y hacia abajo (jdk7: el nuevo elemento apunta al elemento anterior jdk8: el elemento antiguo apunta al nuevo elemento)
4.2. Cuando el elemento en una determinada posición de índice de la matriz es una lista vinculada Cuando el número de formularios existe> 8 y la longitud de la matriz actual es> 64,
todos los datos en la posición de índice ahora se almacenan utilizando árboles rojos y negros. (Alta eficiencia, el árbol binario se puede buscar por la mitad)

if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
        treeifyBin(tab, hash);
        static final int TREEIFY_THRESHOLD = 8

// Se muestra que el código fuente subyacente se expande cuando es menor que 64, y se almacena como un árbol rojo-negro cuando es mayor que 64

 if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
        resize();
        static final int MIN_TREEIFY_CAPACITY = 64

4.3 Las constantes principales del código fuente en la capa inferior de
HashMap : DEFAULT_INITIAL_CAPACITY: la capacidad predeterminada de HashMap: 16
DEFAULT_LOAD_FACTOR: el factor de carga predeterminado de HashMap: 0.75
umbral: el valor crítico de expansión = factor de capacidad de llenado: 16 0.75 => 12
TREETFY_THRESHOLD: la longitud de la lista es mayor que la longitud del bucket Cambie el valor predeterminado a árbol rojo-negro: 8
MIN_TREEIFY_CAPACITY: La capacidad mínima de la tabla hash cuando se activa el nodo en el cubo: 64
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí

Cuarto, el principio de implementación subyacente de LinkedHashMap (subclase de HashMap)

La estructura subyacente de LinkedHashMap es la misma que HashMap, porque LinkedHashMap hereda de HashMap, la diferencia es: LinkedHashMap proporciona un objeto de entrada en el interior, reemplaza Node en HashMap

        源码:
        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. Los métodos definidos en el Mapa:

Agregar, eliminar, modificar operaciones
Poner objeto (clave de objeto, valor de objeto): agrega (o modifica) el valor clave especificado al objeto de mapa actual
void putAll (Mapa m): almacena todos los pares clave-valor en m
Object remove (Object key) en el mapa actual : elimina el par clave-valor especificado y devuelve el valor
void clear (): borra todos los datos en el mapa actual

Operaciones de consulta de elementos:
Object get (Object object): obtiene el valor correspondiente a la clave especificada
boolean usesKey (Object key): si contiene la clave especificada
boolean usesValue (Object value): si contiene el valor especificado
int size (): vuelve al mapa El número de pares clave-valor
boolean isEmpty (): determina si el mapa actual está vacío
boolean igual (Object obj): determina si el mapa actual y el objeto de parámetro obj son iguales

El método de la operación de vista meta
Set keySet (): devuelve todos los
valores de la colección de conjuntos de claves (): devuelve todo el conjunto de valores de la colección
Set entrySet (): devuelve todos los pares clave-valor Set set


public class MapTest {
    //LinkedHashMap:有序,不可重复
    @Test
    public void  test1(){
        Map map = new LinkedHashMap();
        map.put(123,"AA");
        map.put(123,"AA");
        map.put(456,"BB");
        map.put(789,"CC");
        map.put(147,"DD");

        System.out.println(map);
    }
    @Test
    public void test(){
        Map map = new HashMap();
       // map = new Hashtable();//java.lang.NullPointerException,不能存储null的key和value
        map.put(null,null);
    }
    //map方法--- 添加、删除、修改操作
    @Test
    public void test2(){
        Map map = new HashMap();
        //添加
        map.put("AA",123);
        map.put(25,123);
        map.put("AA","BB");//修改覆盖
        map.put(123,"BB");

        System.out.println(map);//{AA=BB, 25=123, 123=BB}

        Map map1 = new HashMap();
        map1.put("CC",123);
        map1.put("DD",123);

        map.putAll(map1);//{AA=BB, CC=123, DD=123, 25=123, 123=BB}
        System.out.println(map);

        //删除
        Object value = map.remove("CC");
        System.out.println(value);//123
        System.out.println(map);//{AA=BB, DD=123, 25=123, 123=BB}

        //clear()
        map.clear();//map = {}
        System.out.println(map.size());//0
    }
    //元素查询的操作
    @Test
    public void  test3(){
        Map map = new HashMap();
        //添加
        map.put("AA",123);
        map.put(25,123);
        map.put("AA","BB");//修改覆盖
        map.put(123,"BB");

        System.out.println(map.get(25));//1233,不存在为null

        boolean isExist = map.containsKey("BB");

        System.out.println(isExist);//false

        boolean isFlag = map.containsValue(123);
        System.out.println(isFlag);//true

        map.clear();


        Map ma1 = new HashMap();
        //添加
        ma1.put("AA",123);
        ma1.put(25,123);
        ma1.put("AA","BB");//修改覆盖
        ma1.put(123,"BB");

        Map ma2 = new HashMap();
        //添加
        ma2.put("AA",123);
        ma2.put(25,123);
        ma2.put("AA","BB");//修改覆盖
        ma2.put(123,"BB");
        System.out.println(map.isEmpty());//true

        System.out.println(ma1.equals(ma2));//true
    }
    @Test
    public void test5(){
//        元视图操作的方法
        Map map = new HashMap();
        //添加
        map.put("AA",123);
        map.put(25,123);
        map.put("AA","BB");//修改覆盖
        map.put(123,"BB");

        //遍历所有的key集合,keySet()
        Set set = map.keySet();

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

        //遍历所有的value集合:values
        Collection values = map.values();
        for (Object obj :values){
            System.out.println(obj);
        }
        //遍历所有的key-value
        //方式一、entrySet()
        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());
        }
        //方式二、
        Set keySet = map.keySet();
        Iterator iterator2 =keySet.iterator();
        while (iterator2.hasNext()){
            Object key = iterator2.next();
            //entrySet集合中的元素都是entry
           Object value = map.get(key);
            System.out.println(key +"-------------->"+ value);
        }

    }

Seis, el uso de TreeMap

Agregue clave-valor a TreeMap, la clave debe ser un objeto creado por la misma clase, porque debe clasificarse de acuerdo con la clave: clasificación natural, clasificación personalizada
Primero, personalice una clase de Persona para la prueba de datos

public class Person implements Comparable {
    public String name;
    public  int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    //重写equals()方法,比较判断contains()中的比较问题

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

        Person person = (Person) o;

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

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }
    //按照姓名从小到大排列,年龄从小到大排序
    @Override
    public int compareTo(Object o) {
       if (o instanceof Person){
           Person person = (Person)o;
//           return  this.name.compareTo(person.name);
           int compare = this.name.compareTo(person.name);
           if (compare !=0){
               return compare;
           }else {
               return  Integer.compare(this.age,person.age);
           }
       }else {
           throw  new RuntimeException("输入的类型不匹配!");
       }
    }
}

Ordenamiento natural

@Test
    public void test(){
        TreeMap map = new TreeMap();
        Person p1 = new Person("Tom",12);
        Person p2 = new Person("Jerry",45);
        Person p3 = new Person("Jack",32);
        Person p4 = new Person("Rose",18);
        Person p5 = new Person("Tm",12);

        map.put(p1,88);
        map.put(p2,88);
        map.put(p3,88);
        map.put(p4,88);
        map.put(p5,88);

        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());
        }
    }

Clasificación personalizada

@Test
    public void  test2(){
        TreeMap map = new TreeMap(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                if (o1 instanceof Person && o2 instanceof Person){
                    Person p1 = (Person)o1;
                    Person p2 = (Person)o2;

                    return  Integer.compare(p1.getAge(),p2.getAge());
                }
                throw new RuntimeException("输入的类型不一致!");
            }
        });
        Person p1 = new Person("Tom",12);
        Person p2 = new Person("Jerry",45);
        Person p3 = new Person("Jack",32);
        Person p4 = new Person("Rose",18);
        Person p5 = new Person("Tm",12);

        map.put(p1,88);
        map.put(p2,88);
        map.put(p3,88);
        map.put(p4,88);
        map.put(p5,88);

        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());
        }
    }

7. Propiedades: una subclase de Hashtable, comúnmente utilizada para procesar archivos de configuración. clave y valor son de tipo String

 public static void main(String[] args) throws  Exception{
        Properties prop = new Properties();

        FileInputStream stream = new FileInputStream("jdbc.properties");

        prop.load(stream);//加载流对应的文件
        String name = prop.getProperty("name");
        String pwd = prop.getProperty("pwd");

        System.out.println("name = "+ name + ",pwd = " + pwd);

        stream.close();
    }
Preguntas de la entrevista:

1. El principio de implementación subyacente de
HashMap 2. ¿Las similitudes y diferencias entre HashMap y Hashtable?
Inserte la descripción de la imagen aquí

Publicado 19 artículos originales · elogiado 0 · visitas 480

Supongo que te gusta

Origin blog.csdn.net/weixin_43244120/article/details/105497524
Recomendado
Clasificación