• 【Java集合】双列集合HashMap的概念、特点及使用
  • 发布于 2个月前
  • 63 热度
    0 评论

上篇文章讲了Map接口的概念,通过他提供的接口方法,我们学习了如何使用以及对Map集合的遍历


HashMap 概念


HashMap集合是Map接口的一个实现类,它用于存储键值映射关系,该集合的键和值允许为空,但键不能重复,且集合中的元素是无序的。


特点

HashMap底层是由哈希表结构组成的,其实就是“数组+链表”的组合体,数组是HashMap的主体结构,链表则主要是为了解决哈希值冲突而存在的分支结构。正因为这样特殊的存储结构,HashMap集合对于元素的增、删、改、查操作表现出的效率都比较高。


结构

在java1.8以后采用数组+链表+红黑树的形势来进行存储,通过散列映射来存储键值对,如下图:


Description


  • 在初始化时将会给定默认容量为16


  • 对key的hashcode进行一个取模操作得到数组下标


  • 数组存储的是一个单链表


  • 数组下标相同将会被放在同一个链表中进行存储


  • 元素是无序排列的


  • 链表超过一定长度(TREEIFY_THRESHOLD=8)会转化为红黑树


  • 红黑树在满足一定条件会再次退回链表


看到这个图,是不是挺熟悉!没错,这个就是我们在讲Set时,它的内存结构图,当时我们说 HashSet的底层就是 Map集合,只不过Set只使用了Map集合中的Key,没有使用Value而已。


小练习

在之前我们已经讲了不少Map的使用方法,本篇中就不做过多解释了,来上了个小练习,在体会下它的使用

每位学生(姓名,年龄)都有自己的家庭住址。那么,既然有对应关系,则将学生对象和家庭住址存储到map集合中。学生作为键, 家庭住址作为值。


注意,学生姓名相同并且年龄相同视为同一名学生。


编写学生类:


public class Student { private String name; private int age; public Student() {
        } public Student(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 boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false;
            Student student = (Student) o; return age == student.age && Objects.equals(name, student.name);
        } @Override public int hashCode() { return Objects.hash(name, age);
        }
    }


编写测试类:


public class HashMapTest { public static void main(String[] args) { //1,创建Hashmap集合对象。 Map<Student,String>map = new HashMap<Student,String>(); //2,添加元素。 map.put(newStudent("lisi",28), "上海");
            map.put(newStudent("wangwu",22), "北京");
            map.put(newStudent("zhaoliu",24), "成都");
            map.put(newStudent("zhouqi",25), "广州");
            map.put(newStudent("wangwu",22), "南京"); //3,取出元素。键找值方式 Set<Student>keySet = map.keySet(); for(Student key: keySet){
                Stringvalue = map.get(key);
                System.out.println(key.toString()+"....."+value);
            }
        }
    }

  • 当给HashMap中存放自定义对象时,如果自定义对象作为key存在,这时要保证对象唯一,必须复写对象的hashCode和equals方法(如果忘记,请回顾HashSet存放自定义对象)。

  • 如果要保证map中存放的key和取出的顺序一致,可以使用java.util.LinkedHashMap集合来存放。


编程学习,从云端源想开始,课程视频、在线书籍、在线编程、一对一咨询……你想要的全部学习资源这里都有,重点是统统免费![点这里即可查看](https://ydcode.cn/memberIndex?sourceId=436)


LinkedHashMap


我们知道HashMap保证成对元素唯一,并且查询速度很快,可是成对元素存放进去是没有顺序的,那么我们要保证有序,还要速度快怎么办呢?


在HashMap下面有一个子类LinkedHashMap,它继承自HashMap。特别的是,LinkedHashMap在HashMap的基础上维护了一个双向链表,可以按照插入顺序或者访问顺序来迭代元素。此外,LinkedHashMap结合了HashMap的数据操作和LinkedList的插入顺序维护的特性,因此也可以被看做是HashMap与LinkedList的结合。它是链表和哈希表组合的一个数据存储结构。把上个练习使用LinkedHashMap的使用一下


publicclass LinkedHashMapDemo { publicstaticvoid main(String[] args) { //Map<String, String> map = new HashMap<String, String>(); LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
            map.put("马云", "阿里巴巴");
            map.put("马化腾", "腾讯");
            map.put("李彦宏", "百度");
            Set<Entry<String, String>> entrySet = map.entrySet(); for (Entry<String, String> entry : entrySet) {
                System.out.println(entry.getKey() + " " + entry.getValue());
            }
        }
    }


总结

本系列文章写到这里,为大家介绍集合家族的知识,基本上就可以告一段落了。


在这个系列文章中,我们讲述了单列和双列集合的家族体系以及简单的使用。集合中不少的实现类,我们并未讲述,大家下来可以通过java的API文档,去学习使用。还是那句话,熟能生巧!只看不练,假把式!


本系列以上内容,都是在实际项目中,会经常碰到这些概念的使用,当然了,文中的内容可能也不是尽善尽美的,如有错误,可以私信,探讨!
happy ending!

用户评论