Map实现类结构情况---知识点(部分)

一:Map实现类结构情况

  • Map 双列数据 用于存储key-value对的数据 ----类似于高中讲的函数 y=f(x)
  •      --HashMap:
            子类 --LinkedHashMap:
    
  •      -- TreeMap:
    
  •      --Hashtable:
           子类     --Properties:
    

区别

1.HashMap:作为我们的主要实现类,线程是不安全的,所以效率很高,可以存放null的key和value
2.Hashtable:作为我们古老的实现类 在1.2时候才有,线程是安全的,所以效率很低 是不能存放key和value的

public class MapTest {
    @Test
    public void test1(){
//        Map map = new HashMap();
        Hashtable map = new Hashtable();
        map.put(null,123);
        map.put(null,null);
        System.out.println();
    }
}

3.LinkedHashMap:能够保证在遍历的时候 是按照添加的顺序进行输出的,原因是:在原有的HashMap底层的基础上,添加了一对指针
指向前一个元素,对于频繁的进行遍历操作,我们当前的LinkedHashMap要高于我们的HashMap。

4.TreeMap:可以按照添加的key-value进行排序,实现排序的遍历 此时考虑key的自然排序,或者定制排序。底层使用对的是红黑树

注意:HashMap底层:数据+链表,仅限(jdk1.7之前)在(jdk8中) 是数组+链表+红黑树

5.Properties :常用来处理配置文件 key和value都是String 类型

面试题:

HashMap 的底层原理:

HashMap 和 Hashtable 的区别

CurrentHashMap 和Hashtable 异同(暂时不说)

二:Map结构的理解

  • Map中是无序的,不可以重复的,使用set进行存放所有的key,---->要求我们所在的类要重写equals()和hashCode()方法(依HashMap举例)
  • Map中的value是无序的,可以重复的,使用Collection存放所有的value,所在的类要重写equals()方法
  • 一个键值对构成了一个Entry对象
  • Map中的entry:无序的,不可以重复的,使用set存放所有的entry

HashMap 的底层实现原理

  • 以jdk7为例
HashMap map = new HashMap();
  • 在实例化的时候底层创建了一个长度是16的一维数组,Entry[] table

    ...可能已经执行多次的put()方法了
  map.put(key1,value1)往里面添加数据 <br>
  • 1.首先先调用key1所在类的hashCode()方法,计算key1的哈希值,此哈希值经过某种算法之后 得到Entry数组中存放的位置
  • 2.如果此位置上数据为空,此时key1-value1添加成功 ---情况一
  • 3.如果此位置上数据不为空,(意味着此位置上存在一个或者多个数据(已链表的形式存在) 比较key1和已经存在的一个或者多个数据的哈希值
    • 如果key1的哈希值和已经存在的hash数值都不同,此时的key1-value1添加成功----情况二
    • 如果key1的哈希值和已经存在的某个数据(key2-value2)哈希值相同,继续比较,调用key1所在类中equals(key2)方法,比较
    • 有两种情况
    • 1.如果equals()返回的是false 则证明添加成功---情况三
    • 2.如果equals()返回的是true 使用value1替换value2

说明:情况二和情况三 此时的key1-value1和原来的数据以链表的方式存储,再添加的时候会涉及的扩容问题,扩容原来的2倍,并将原来的复制过来

  • 在jdk8中相对于jdk7中的不同
  • 1.底层没有长度为16的数组
  • 2.jdk8中底层的数组是Node[] 而非 Entry[]数组
  • 3.首次调用put方法时候底层会创建长度为16的数组
  • 4.jdk7中只有数组+链表 在jdk8中;数组+链表+红黑树
  • 当数组某一个索引的位置上面的元素以链表形式的存在的数据个数>8 且当前数组的长度>64的时候,此时索引上的数组改为使用红黑树进行存放

Map的常用方法:

添加


import org.junit.Test;

import java.util.HashMap;
import java.util.Map;

public class MapTest {
    // 添加
    @Test
    public void test1(){
        Map map = new HashMap();
        map.put("AA",123);
        map.put(545,123);
        map.put("BB",123);
        System.out.println(map);
    }
}

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

        Map map1 = new HashMap();
        map.put("CC",123);
        map.put("DD",123);
        map.putAll(map1);
        System.out.println(map);

    }

删除

    @Test
    public void test3(){
        Map map = new HashMap();
        map.put("AA",123);
        map.put("BB",123);
        map.put("CC",123);
        map.put("DD",123);
        map.remove("DD");
        System.out.println(map);
    }
    //没有的话返回值就是null

清空数据

 @Test
    public void test4() {
        Map map = new HashMap();
        map.put("AA", 123);
        map.put("BB", 123);
        map.put("CC", 123);
        map.put("DD", 123);
        map.clear();
        System.out.println(map);
    }
    //调用map.size()方法不会出现空指针异常,结果是0

查询指定元素

   //元素查询
    @Test
    public void test5() {
        Map map = new HashMap();
        map.put("AA", 123);
        map.put("BB", 123);
        map.put("CC", 123);
        map.put("DD", 123);
        System.out.println(map.get(45));
    }

判断当前的map是否包含当前的key或者value

   @Test
    public void test6() {
        Map map = new HashMap();
        map.put("AA", 123);
        map.put("BB", 123);
        map.put("CC", 123);
        map.put("DD", 123);
        boolean isExist = map.containsKey("BB");
        System.out.println(isExist);
    }

是否包含指定的value方法

    @Test
    public void test7() {
        Map map = new HashMap();
        map.put("AA", 123);
        map.put("BB",789);
        map.put("CC", 456);
        map.put("DD", 123);
        boolean isExist= map.containsValue(123);
        System.out.println(isExist);
    }

元视图操作方法

  • 遍历所有的Key方法
@Test
    public void test8() {
        Map map = new HashMap();
        map.put("AA", 123);
        map.put("BB", 789);
        map.put("CC", 456);
        map.put("DD", 123);
        //遍历所有的key
        Set set = map.keySet();
        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }

遍历所有的value

    @Test
    public void test9() {
        Map map = new HashMap();
        map.put("AA", 123);
        map.put("BB", 789);
        map.put("CC", 456);
        map.put("DD", 123);
        //遍历所有的key
        Collection values = map.values();
        Iterator iterator = values.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }

遍历所有的key-value

    @Test
    public void test1_1() {
        Map map = new HashMap();
        map.put("AA", 123);
        map.put("BB", 789);
        map.put("CC", 456);
        map.put("DD", 123);
        Set set = map.entrySet();
        for (Object o : set) {
            System.out.println(o);
        }
    }

TreeMap两种添加方式的使用

向TreeMap中添加key-value 要求key必须是由同一个类创建的对象,因为我们要按照key进行排序,不能按照Value进行排序,排序方式:自然排序,定制排序(使用Comparator然后按照想要的进行排序)

//自然排序
    @Test
    public void test1(){
        TreeMap map = new TreeMap();
        map.put("AA",123);
        map.put("BB",345);
        map.put("EE",567);
        Set set = map.entrySet();
        Iterator iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }

Properties说明


import org.junit.Test;

import java.io.FileInputStream;
import java.util.Properties;

public class PropertiesTest {
    @Test
    public void test() throws Exception {
        Properties properties = new Properties();
        //进行读取
        FileInputStream is = new FileInputStream("jdbc.properties");
        properties.load(is);
//        properties.load(is);//加载流对应的文件
        //读取配置文件
        String name = properties.getProperty("name");
        String password = properties.getProperty("password");
        System.out.println("姓名:"+name+"----密码:"+password);
    }
}

Collections工具类的使用

Collections:操作Collection,Map的工具类

面试题Collections和Collection的区别:

  • Collection 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式。
  • Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。
  • Collections 是一个包装类,Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许,一些 collection 是有序的,而另一些则是无序的。

常用方法

  • 反转
import org.junit.Test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollectionTest {
    @Test
    public void test() {
        //进行反转
        List list = new ArrayList();
        list.add(123);
        list.add(433);
        list.add(235);
        list.add(876);
        System.out.println(list);
        Collections.reverse(list);
        System.out.println(list);
    }
}

  • 随机化输出
    @Test
    public void test1() {
        //随机化输出
        List list = new ArrayList();
        list.add(123);
        list.add(433);
        list.add(235);
        list.add(876);
        System.out.println(list);
        Collections.shuffle(list);
        System.out.println(list);
    }
  • 自然排序
@Test
    public void test2() {
        //自然排序
        List list = new ArrayList();
        list.add(123);
        list.add(433);
        list.add(235);
        list.add(876);
        System.out.println(list);
        Collections.sort(list);
        System.out.println(list);
    }

  • 交换索引位置上的元素
    @Test
    public void test3() {
        //交换索引位置上的元素
        List list = new ArrayList();
        list.add(123);
        list.add(433);
        list.add(235);
        list.add(876);
        System.out.println(list);
        Collections.swap(list,1,2);
        System.out.println(list);
    }
  • 返回指定集合中指定元素的出现次数
 @Test
    public void test4() {
        //交换索引位置上的元素
        List list = new ArrayList();
        list.add(123);
        list.add(433);
        list.add(235);
        list.add(235);
        list.add(876);
        System.out.println(list);
        Collections.frequency(list,235);
        System.out.println(list);
    }
  • 将src中的内容复制到dest中
    @Test
    public void test5() {
        //复制
        List list = new ArrayList();
        list.add(123);
        list.add(433);
        list.add(235);
        list.add(235);
        list.add(876);
//        System.out.println(list);
//        List dest = new ArrayList();
//        dest.add(3232);
//        dest.add(3232);
//        dest.add(3232);
//        dest.add(3232);
//        dest.add(3232);

        List dest = Arrays.asList(new Object[list.size()]);
        Collections.copy(dest,list);
        System.out.println(dest);
    }

posted @ 2022-04-05 17:24  秃头星人  阅读(61)  评论(0编辑  收藏  举报