Java基础学习——Java集合(九)Map接口、HashMap、LinkedHashMap实现类、TreeMap实现类

一、Map接口

二、HashMap实现类、LinkedHashMap实现类

1.HashMap的特点

1)无序,唯一(key唯一,因为底层key按照哈希表(数组+链表)的结构)

2)放入集合的数据的类中,必须重写hashCode()和equals()

2.HashMap常用方法

1)增:put(Key key,V value)

2)删:clear()

             remove(Object key)

3)改:

4)查:size()

             keySet():返回key

             values():返回value

             get(Object key):根据key得到value

             entrySet():返回key和value

5)判断:containsKey(Object key):是否存在key

                containsValue(Object value):是否存在value

                 equals(Object o):两个集合元素是否相等

                 isEmpty()

package com.rzd.no03map;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class Demo01 {
    public static void main(String[] args) {
        //创建一个Map集合来表示学生的学号、姓名键值对,使用Map接口下的HashMap实现类来创建
        Map<Integer, String> hm = new HashMap<>();

        //常用方法
        System.out.println("增:");
        //1.增:put(Key key,V value)
        hm.put(1001, "lili");
        //System.out.println(hm1.put(1001, "lili")); 如果对上面一句的返回结果进行输入,得到的结果是null
        hm.put(1001, "alili");
        //System.out.println(hm1.put(1001, "lili")); 添加key相同而value不相同的数据,返回结果是value值alili,说明添加的是这条数据
        hm.put(1005,"nana");
        hm.put(1028,"feifei");
        hm.put(1012,"feifei");
        hm.put(1018,"taotao");
        System.out.println(hm.size()); //5
        System.out.println(hm);    //Map集合,无序,唯一(key唯一),{1028=feifei, 1012=feifei, 1001=alili, 1018=taotao, 1005=nana}

        System.out.println("删:");
        //2.删:remove(Object key)、clear()
        hm.remove(1018);
        System.out.println(hm);    //{1028=feifei, 1012=feifei, 1001=alili, 1005=nana}
        /*hm1.clear();
        System.out.println(hm1);    //{}*/

        System.out.println("查:");
        //3.查:entrySet()、get(Object key)、keySet()、size()、values()
        //对集合中进行遍历查看
        //1)keySet():遍历key,返回的是一个Set集合,且这个集合里面的参数类型是key的类型。
        //所以创建一个Set类型的对象来接收
        Set<Integer> set = hm.keySet();
        //对set使用for循环遍历
        for (Integer i:set){
            System.out.print(i+"\t");    //1028	1012	1001	1005
        }
        System.out.println();

        //2)values():遍历value,返回的是一个Collection集合,集合的参数类型是value的类型。
        //所以创建一个Collection类型的对象来接收
        Collection<String> values = hm.values();
        //对values使用for循环遍历
        for (String s:values){
            System.out.print(s+"\t");   //feifei	feifei	alili	nana
        }
        System.out.println();

        //3)get(Object key):通过key的值遍历value
        //先创建一个对象接收key的值,通过调用hm1.get(key)得到该方法的返回值value
        Set<Integer> set1 = hm.keySet();
        for (Integer i:set1){
            System.out.print(hm.get(i)+"\t");    //feifei	feifei	alili	nana
        }
        System.out.println();

        //4)entrySet():返回值是一个Set集合,Set集合里的每一个元素都是
        //Map(接口)集合里面的Entry(接口)的一个具体的对象,这个对象就是key和value的封装
        Set<Map.Entry<Integer, String>> entries = hm.entrySet();
        //对Set集合进行遍历
        for (Map.Entry<Integer, String> e:entries){ //参考上面写的也是引用类型 参数名:对象
            System.out.print(e.getKey()+"="+e.getValue()+"\t");
            }

        System.out.println();
        System.out.println("判断:");
        //4.判断:
        //containsKey(Object key):集合中是否包含key
        System.out.println(hm.containsKey(1028));  //true
        System.out.println(hm.containsKey(1111));  //false
        //containsValue(Object value):集合中是否包含key
        System.out.println(hm.containsValue("nana"));  //true

        //equals(Object o):判断两个集合元素是否相同
        Map<Integer, String> hm1 = new HashMap<>();
        hm1.put(1111,"aaaa");
        hm1.put(2222,"bbbb");
        hm1.put(3333,"cccc");
        hm1.put(4444,"dddd");
        Map<Integer, String> hm2 = new HashMap<>();
        hm2.put(1111,"aaaa");
        hm2.put(2222,"bbbb");
        hm2.put(3333,"cccc");
        System.out.println(hm1==hm2);   //false,判断集合地址是否相同
        System.out.println(hm1.equals(hm2));    //true,判断集合元素是否相同,说明Map中对equals方法进行了重写

        //isEmpty():判断是否为空
        hm.clear();
        System.out.println(hm.isEmpty());   //true
    }
}

3.LinkedHashMap实现类

按照输入的顺序输出HashMap,底层是哈希表+链表

特点:唯一,有序(按照输入的顺序输出)

        Map<Integer, String> hm = new LinkedHashMap<>();
        hm.put(1001, "lili");
        hm.put(1001, "alili");
        hm.put(1005,"nana");
        hm.put(1028,"feifei");
        hm.put(1012,"feifei");
        hm.put(1018,"taotao");
        System.out.println(hm.size()); //5
        System.out.println(hm);    //{1001=alili, 1005=nana, 1028=feifei, 1012=feifei, 1018=taotao}

4、Hashtable实现类

使用与HashMap相同

区别为:

HashMap:JDK1.2开始,效率高,线程不安全,可以存入key为空的元素,且也遵循key唯一的特点。

Hashtable:JDK1.0开始,效率低,线程安全,不能存入key为空的元素,会报NullPointerException空指针异常

三、HashMap源码分析

1.原理分析

创建一个HashMap集合存放学生年龄-姓名键值对

可以看到,有两条key为1的数据,put命令的返回值为当前的value,对于hm.put(10, "明明")返回的时null,说明存入的不是这条数据,对于hm.put(10, "花花"),返回值却是"明明"。这里就需要分析原理及源码来解释。

public class Demo03 {
    public static void main(String[] args) {
        HashMap<Integer, String> hm = new HashMap<>();
        System.out.println(hm.put(10, "明明"));   //null,说明存入的不是这条的key
        hm.put(15,"红红");
        hm.put(13,"兰兰");
        System.out.println(hm.put(10, "花花"));   //输出了value值"明明"
        hm.put(19,"菲菲");
        System.out.println(hm.size());
        System.out.println(hm);//{19=菲菲, 10=花花, 13=兰兰, 15=红红} 无序,唯一
    }
}

2.源码分析

1)HashMap的泛型<K,V>在创建对象的时候就确定了,这里K=Integer,V=String

HashMao实现了Map接口,但是HashMap继承的AbstractMap类也实现了Map接口,这是一种荣誉冗余写法

2)DEFAULT_INITIAL_CAPACITY:默认的初始化长度,定定义了要赋给数组长度的值16

1<<4,表示1左移4位,0000 0001 左移4位:0001 0000=2的4次方=16

 3)MAXIMUM_CAPACITY:1左移30位,每左移1位就是乘以2,这里可以看到是定义了一个非常大的数

 4)DEFAULT_LOAD_FACTOR=0.75:负载因子/加载因子,后面会将0.75赋给loadFactor

 

5)底层主数组为Entry类型

6)size:集合中添加的元素的个数

7) threshold:默认为0,用来表示数组扩容的边界值

8)无参构造器

 

9)put()

返回值是 

四、TreeMap实现类

1.特点

唯一,有序(按照升序或降序)

底层原理:二叉树,key遵照二叉树的特点,且放入集合的类需要实现内部或外部比较器

2.TreeMap的使用

1)key为String类型数据

可以看到遵循key升序的顺序排序

        //创建学生姓名-学号键值对
        Map<String,Integer> tm = new TreeMap<>();
        tm.put("alili",1001);
        tm.put("clili",1032);
        tm.put("elili",1007);
        tm.put("blili",1011);
        tm.put("dlili",1001);
        System.out.println(tm); //{alili=1001, blili=1011, clili=1032, dlili=1001, elili=1007}

2)key为自定义的类型数据

内部比较器

class Student implements Comparable<Student>{
    String name;
    int age;
    double height;

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

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public Student(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }

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

    //内部比较器

    @Override
    public int compareTo(Student o) {
        //return 0;
        return this.getAge()-o.getAge();
    }
}
 //key为自定义的类
        //内部比较器
        Map<Student, Integer> tm1 = new TreeMap<>();
        tm1.put(new Student("alili",13,150.8),1001);
        tm1.put(new Student("clili",19,180.3),1032);
        tm1.put(new Student("elili",28,160.8),1007);
        tm1.put(new Student("blili",7,199.2),1011);
        tm1.put(new Student("dlili",14,148.6),1001);
        System.out.println(tm1);
        //{Student{name='blili', age=7, height=199.2}=1011,
        // Student{name='alili', age=13, height=150.8}=1001,
        // Student{name='dlili', age=14, height=148.6}=1001,
        // Student{name='clili', age=19, height=180.3}=1032,
        // Student{name='elili', age=28, height=160.8}=1007}

外部比较器

//外部比较器
class Bijiao1 implements Comparator<Student>{
    @Override
    public int compare(Student o1, Student o2) {
        //return 0;
        return o1.getAge()-o2.getAge();
    }
}
class Bijiao2 implements Comparator<Student>{
    @Override
    public int compare(Student o1, Student o2) {
        //return 0;
        return o1.getName().compareTo(o2.getName());
    }
}
class Bijiao3 implements Comparator<Student>{
    @Override
    public int compare(Student o1, Student o2) {
        //return 0;
        return ((Double)(o1.getHeight())).compareTo((Double)(o2.getHeight()));
    }
}
        //外部比较器
        //需要先创建外部比较器对象
        Comparator bj3 = new Bijiao3();
        Map<Student, Integer> tm2 = new TreeMap<>(bj3);
        tm2.put(new Student("alili",13,150.8),1001);
        tm2.put(new Student("clili",19,180.3),1032);
        tm2.put(new Student("elili",28,160.8),1007);
        tm2.put(new Student("blili",7,199.2),1011);
        tm2.put(new Student("dlili",14,148.6),1001);
        System.out.println(tm2);
        //{Student{name='dlili', age=14, height=148.6}=1001, 
        // Student{name='alili', age=13, height=150.8}=1001, 
        // Student{name='elili', age=28, height=160.8}=1007, 
        // Student{name='clili', age=19, height=180.3}=1032, 
        // Student{name='blili', age=7, height=199.2}=1011}

匿名内部类

         //匿名内部类写法
        Map<Student, Integer> tm3 = new TreeMap<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                //return 0;
                return o1.getName().compareTo(o2.getName());
            }
        });
        tm3.put(new Student("alili",13,150.8),1001);
        tm3.put(new Student("clili",19,180.3),1032);
        tm3.put(new Student("elili",28,160.8),1007);
        tm3.put(new Student("blili",7,199.2),1011);
        tm3.put(new Student("dlili",14,148.6),1001);
        System.out.println(tm3);
        //{Student{name='alili', age=13, height=150.8}=1001, 
        // Student{name='blili', age=7, height=199.2}=1011, 
        // Student{name='clili', age=19, height=180.3}=1032,
        // Student{name='dlili', age=14, height=148.6}=1001, 
        // Student{name='elili', age=28, height=160.8}=1007}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值