1.Map的实现类的结构

Map: 双列数据,存储key-value对的数据。

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

在这里插入图片描述

  • Map结构的理解
  • Map中的key:无序的、不看重复的,使用Set存储所有的key —->key所在类要重写equals()和hashCode().
  • Map中的value:无序的、可重复的,使用Collection存储所有的value, —>value所在类要重写equals().
  • 一个键值对:key-value构成了一个Entry对象。
  • Map中的entry:无序、不可重复的、使用Set存储所有的entry。

2.HashMap的底层实现原理(以JDK7为说明)

 HashMap map=new HashMap(); //在实例化以后,底层创建了长度为16的一维数组Entry[] table。
 -----可能已经执行过多次put()------
 map.put(key1,value1):
 首先,调用key1所在类的hashCode()计算key1哈希值,此哈希值经过某种算法计算以后,得到Entry数组中的存放位置。
 - 如果此位置上的数据为空,此时key1-value1添加成功。  ----情况1
 - 如果此位置上的数据不为空,(意味着此位置上存在一个或多个数据(以链表形式存在)),
   比较key1和已经存在的一个或多个数据的哈希值:
        --如果key1的哈希值与已经存在的数据的哈希值不相同,此时key1-value1添加成功   ---情况2
        --如果key1的哈希值和已经存在的某一个数据(key2-value2)的哈希值相同,
          继续比较:调用key1所在类的equals(keys)---如果equals返回false:此时key1-value1添加成功。  ---情况3
          ---如果equals返回true:使用value1替换value2。
  -补充:关于情况2和情况3:此时key1-value1和原来的数据以链表的方式存储。
  -在不断的添加过程中,会涉及到扩容问题,当超出临界值(且要存放的位置非空),扩容。默认的扩容方式:扩容为原来容量的2倍,并将原有数据复制过来。
 
- JDK8相较于JDK7在底层实现方面的不同:
  1.new HashMap():底层没有创建一个长度为16的数组
  2.JDK8底层的数组是:Node[],而非Entry[]
  3.首次调用put()方法时,底层创建长度为16的数组。
  4.JDK7底层结构只有:数组+链表。JDK8中底层结构:数组+链表+红黑树。
    当数组的某一个索引位置上的元素以链表形式存在的数据个数 >8 且当前数组的长度 >64时,
    此时此索引位置上的所有数据改为使用红黑树存储。

3.LinkedHashMap的底层实现原理

源码中:
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);
   }
}

4.Map接口:常用方法

  • 添加、删除、修改操作:
    Object put(Object key,Object value): 将指定key-value添加到(或修改)当前map对象中。
    void putAll(Map m): 将m中的所有key-value存放到当前map中。
    Object remove(Object key): 移除指定的key的key-value对,并返回value。
    void clear(): 清空当前map中的所有数据。
  • 元素查询的操作:
    Object get(Object key): 获取指定key对应的value.
    boolean containsKey(Object key): 是否包含指定的key.
    boolean containsValue(Object value): 是否包含指定的value。
    int size(): 返回map中key-value对的个数。
    boolean isEmpty(): 判断当前map是否为空。
    boolean equals(Object obj): 判断当前map和参数对象obj是否相等。
  • 元视图操作的方法:
    Set keySet(): 返回所有key构成的Set集合。
    Collection values(): 返回所有value构成的Collection集合。
    Set entrySet(): 返回所有key-value对构成的Set集合。
  • 遍历HashMap集合
 Map map=new HashMap();
 map.put("AA",123);
 map.put(45,1234);
 map.put("BB",56);

 //遍历所有的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();
   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();
  Ojbect value=map.get(key);
  System.out.println(key+"===="+value);
}

5.TreeMap

  • 自然排序

import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class TreeMapTest {
    //向TreeMap中添加key-value,要求key必须是由同一个类创建的对象。
    //因为是要按照key进行排序:自然排序,定制排序


    public static void main(String[] args) {
        //自然排序
       TreeMap map=new TreeMap();
       Person p1=new Person("Tom",18);
       Person p2=new Person("Jerry",20);
       Person p3=new Person("Jack",19);
       Person p4=new Person("Rose",24);

       map.put(p1,98);
       map.put(p2,89);
       map.put(p3,76);
       map.put(p4,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());
       }


    }
}
import java.util.Objects;

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

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = 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 +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        System.out.println("Person equals....");
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }


    //按照姓名从小到大排列
    @Override
    public int compareTo(Object o) {
        //如果是Person
        if (o instanceof Person){
            Person person=(Person) o;
            //按照姓名从小到大排列:return this.name.compareTo(person.name);
            //按照姓名从大到小排列:  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("输入的类型不匹配!");
        }
    }
}
  • 定制排序

import java.util.*;

public class TreeMapTest {
    //向TreeMap中添加key-value,要求key必须是由同一个类创建的对象。
    //因为是要按照key进行排序:自然排序,定制排序


    public static void main(String[] args) {
        //定制排序:年龄从小到大
       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",18);
       Person p2=new Person("Jerry",20);
       Person p3=new Person("Jack",19);
       Person p4=new Person("Rose",24);

       map.put(p1,98);
       map.put(p2,89);
       map.put(p3,76);
       map.put(p4,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.Properties

  • Properties类是Hashtable的子类,对该对象用于处理属性文件。
  • 由于属性文件里的key、value都是字符串类型,所以Properties里的key和value都是字符串类型。
  • 存取数据时,建议使用setProperty(String key,String value)方法和getProperty(String key)方法。

	Properties pros=new Properties();
	pros.load(new FileInputStream("jdbc.properties"));
	String user=pros.getProperty("user");
	System.out.println(user);


版权声明:本文为RufyHuang原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/RufyHuang/article/details/108088977