一、hashmap底层原理:

hashmap调用默认构造方法会产生一个默认底层是长度为16的Entry数组,首先调用key的hasCode()方法来得到一个整数, int hash = hash(key.hashCode());
 这个整数就是哈希码,然后把哈希码作为参数传递到hash()函数中来进行运算,即散列运算,得到一个int类型的散列值 int i = indexFor(hash, table.length); (transient Entry[] table;) 把散列值和数组的长度来进行运算,最终得到Entry对象要存放到数组的位置(下标)。 hashmap内部的结构是数组加单向链表结构,因为不同的key有可能计算出相同的散列值,根据散列值计算出来的存放到数组的下标会冲突(同一个下标值),此时, 如果键相同,散列值也一样,说明是同一个对象,此时会将键所对应的旧值用新的键值覆盖掉, 如果散列值一样,键名不一样,说明是不同的对象,此时会把键值对封装成entry对象放到那个散列值对应的下标位置处, 原来那个entry对象会以链表形式链接在新创建的entry对象后面

二、hashmap常用方法:

 存值:public V put(K key, V value)

取值:public V get(Object key) 

获取所有的键:public Set<K> keySet()

获取所有的值: public Collection<V> values()    Returns a {@link Collection} view of the values contained in this map.

取键值对的set集合:public Set<Map.Entry<K,V>> entrySet()

 map集合大小:public int size()

 判断map是否非空:public boolean isEmpty()

三、示例:

  1. package com.iotek.map;
  2.  
  3. import java.util.Collection;
  4. import java.util.HashMap;
  5. import java.util.Map;
  6. import java.util.Map.Entry;
  7. import java.util.Set;
  8.  
  9. public class HashMapDemo1 {
  10. public static void main(String[] args) {
  11. Map<String, String> map = new HashMap<String, String>(); // 接口的引用变量指向实现类的对象
  12. // 创建HashMap对象,也就是创建一个Map容器
  13. map.put(null, "张三"); // 添加键值对元素
  14. map.put(null, "李四"); // 有相同的键时,后面添加的键对应的值会覆盖掉之前键对应的值
  15. map.put("john", "李四");
  16. map.put("rose", "玫瑰");
  17. map.put("mary", "小红");
  18. System.out.println("1" + map);
  19.  
  20. // 获取map中所有键,返回的是一个Set容器,可以用迭代器对象或者foreach来进行输出
  21. Set<String> keys = map.keySet();
  22. System.out.println("******输出map容器中所有的键:");
  23. for (String key : keys) {
  24. System.out.print(key + " "); // 用String类型的变量key来遍历keys容器
  25. }
  26.  
  27. // 获取map中所有的值:使用map接口中的values方法,返回Collection接口的实现类
  28. Collection<String> values = map.values();
  29. System.out.println("\n******输出map容器中所有的值:");
  30. for (String value : values) {
  31. System.out.print(value + " "); // 用String类型的变量value来遍历values容器
  32. }
  33.  
  34. // 得到key的同时,得到key所对应的值
  35. System.out.println("\n******用获取的键来得到对应的值并输出:");
  36. for (String key : keys) {
  37. System.out.print(key + "--" + map.get(key)); // 用String类型的变量key来遍历keys容器
  38. }
  39. System.out.println("\nmap容器中键值对的个数是:" + map.size());
  40. System.out.println("判断map容器中是否为空:" + map.isEmpty());
  41.  
  42. // map.entrySet()返回的是一个set容器,其中放的是map.Entry内部接口
  43. /*
  44. * 当我们调用put(key,value)方法时,首先会把key和value封装到Entry这个静态内部类中,
  45. * 再把Entry对象添加到数组中(哈希表),所以我们想要获取map中的所有键值对,只需要获取
  46. * 数组汇总所有的Entry,接下来调用Entry对象中的getKey 和getValue方法就能获取键值对
  47. * 以后想输出HashMap容器中所有的键值对,都可以调用HashMap的 entrySet()方法就可以了!!!
  48. */
  49. Set<Entry<String, String>> entrys = map.entrySet();
  50. System.out.println("使用map接口的entrySet()方法获取map容器中所有的键值对:");
  51. for (Entry<String, String> entry : entrys) {
  52. System.out.println(entry.getKey() + "-" + entry.getValue());
  53. }
  54. map.clear();
  55. System.out.println("判断map容器中是否为空:" + map.isEmpty());
  56.  
  57. }
  58.  
  59. }

map中键是对象时,需要重写对象的hash和equals方法:

  1. package com.iotek.map;
  2.  
  3. import java.util.HashMap;
  4. import java.util.Map;
  5.  
  6. public class HashMapDemo2 {
  7.  
  8. /**
  9. * @param args
  10. */
  11. public static void main(String[] args) {
  12. Map<Student, String> map = new HashMap<Student, String>();
  13. map.put(new Student("jay", 20), "张三"); //
  14. map.put(new Student("lisi", 30), "李四");//
  15. map.put(new Student("rose", 20), "玫瑰");//
  16. map.put(new Student("lisi", 30), "陈飞");//
  17. System.out.println(map.size());
  18. System.out.println(map.toString());
  19.  
  20. /*
  21. * Student类中不重写hashCode() and
  22. * equals()方法,此处map.size()值是4,即map中有4个封装了键值对的Entry对象
  23. * 重写了hashCode()和equals()方法后,2和4语句里的学生对象将被判断为同一个键名,因此2位置处的键值会被替换掉
  24. * 这正是我们需要的,对象相同,应该判定为是同一个键,因此,这就是需要重写hashCode()和equals()方法的原因
  25. */
  26. }
  27. }
  28.  
  29. class Student {
  30. private String name;
  31. private int age;
  32.  
  33. @Override
  34. public int hashCode() {
  35. final int prime = 31;
  36. int result = 1;
  37. result = prime * result + age;
  38. result = prime * result + ((name == null) ? 0 : name.hashCode());
  39. return result;
  40. }
  41. /*
  42. * 用source中的 Generate hashCode() and equals() 来 生成重写的hashCode()方法和equals()方法
  43. * 只要姓名和年龄相同的学生,那么这个学生对象产生的hashCode值和equals方法的值也是一样的,
  44. * 此时就可以认为是hashmap里放的是同一个对象,那么这两个相同的Student对象作为键时,
  45. * 后面添加的Student对象对应的键值应该要覆盖掉前面添加的键值
  46. */
  47.  
  48. @Override
  49. public boolean equals(Object obj) {
  50. if (this == obj)
  51. return true;
  52. if (obj == null)
  53. return false;
  54. if (getClass() != obj.getClass())
  55. return false;
  56. Student other = (Student) obj;
  57. if (age != other.age)
  58. return false;
  59. if (name == null) {
  60. if (other.name != null)
  61. return false;
  62. } else if (!name.equals(other.name))
  63. return false;
  64. return true; // 只有当姓名和年龄都一样时,才返回一个true,表示是同一个对象
  65. }
  66.  
  67. public Student(String name, int age) {
  68. super();
  69. this.name = name;
  70. this.age = age;
  71. }
  72.  
  73. public String getName() {
  74. return name;
  75. }
  76.  
  77. public void setName(String name) {
  78. this.name = name;
  79. }
  80.  
  81. public int getAge() {
  82. return age;
  83. }
  84.  
  85. public void setAge(int age) {
  86. this.age = age;
  87. }
  88.  
  89. @Override
  90. public String toString() {
  91. return "Student [name=" + name + ", age=" + age + "]";
  92. }
  93.  
  94. }

结果:

  1. 使用hashmap判断数组中字符串出现的次数:
  1. package com.iotek.map;
  2.  
  3. import java.util.HashMap;
  4. import java.util.Map;
  5. import java.util.Map.Entry;
  6. import java.util.Set;
  7. /**
  8. * 使用hashmap判断数组中字符串出现的次数
  9. * @author Administrator
  10. *
  11. */
  12. public class AccountStringDemo {
  13.  
  14. public static void main(String[] args) {
  15. String[] strs = {"zhangsan","zhangsan","wangwu","chenliu","chenliu","lilei","lilei"};
  16. Map<String,Integer> data = AccountUtil.account(strs);
  17. AccountUtil.printData(data);
  18. }
  19.  
  20. }
  21.  
  22. class AccountUtil {
  23. public static Map<String,Integer> account(String [] strs) {
  24. Map<String,Integer> data = new HashMap<String, Integer>();
  25. for(int i = 0; i < strs.length; i++) {
  26. String str = strs[i];
  27. if(data.get(str) == null) {
  28. data.put(str, 1);
  29. //如果第一次统计到该字符串,将该字符串作为键名,其出现的次数作为键值,保存在map容器中
  30. } else {
  31. //如果不是第一次捕获到该字符串,则data.get(str)!=null,那么将键值加1,表示第二次读取到该字符串
  32. data.put(str, data.get(str)+1);
  33. }
  34. }
  35. return data; //将最终的hashmap容器,也就是data返回
  36. }
  37.  
  38. public static void printData(Map<String,Integer> data) {
  39. //使用HashMap的EntrySet()方法,返回map容器:data中的所有键值对(全部封装在Entry中),然后进行打印
  40. Set<Entry<String, Integer>> entrys = data.entrySet();
  41. for(Entry<String, Integer> entry : entrys) {
  42. System.out.println("字符串" + entry.getKey() + "出现了" + entry.getValue() + "次");
  43. }
  44. }
  45.  
  46. }

ht-4 hashmap特性的更多相关文章

  1. hashMap 底层原理+LinkedHashMap 底层原理+常见面试题

    1.源码 java1.7    hashMap 底层实现是数组+链表 java1.8 对上面进行优化  数组+链表+红黑树 2.hashmap  是怎么保存数据的. 在hashmap 中有这样一个结构 ...

  2. ysoserial分析【二】7u21和URLDNS

    目录 7u21 gadget链分析 hashCode绕过 参考 URLDNS 7u21 7u21中利用了TemplatesImpl来执行命令,结合动态代理.AnnotationInvocationHa ...

  3. YsoSerial 工具常用Payload分析之URLDNS

    本文假设你对Java基本数据结构.Java反序列化.高级特性(反射.动态代理)等有一定的了解. 背景 YsoSerial是一款反序列化利用的便捷工具,可以很方便的生成基于多种环境的反序列化EXP.ja ...

  4. Leetcode分类刷题答案&心得

    Array 448.找出数组中所有消失的数 要求:整型数组取值为 1 ≤ a[i] ≤ n,n是数组大小,一些元素重复出现,找出[1,n]中没出现的数,实现时时间复杂度为O(n),并不占额外空间 思路 ...

  5. SpringMVC无法获取请求中的参数的问题的调查与解决(2)

    由于Request的getInputSteam()一旦获取一次后,就再也无法获取了 在实际项目中导致下面的问题: 1,多个拦截器,Filter都需要从InputStream中拿数据的情况无法处理: 2 ...

  6. Java中的集合类

    实线边框的是实现类,比如ArrayList,LinkedList,HashMap等 折线边框的是抽象类,比如AbstractCollection,AbstractList,AbstractMap等, ...

  7. AnnotationUtils

    /** * 查询类中符合指定annotation的属性信息 * @param objCls 实体类 * @param annCls 注解类 * @return HashMap<实体属性名, An ...

  8. MapReduce并行编程模型和框架

    传统的串行处理方式 有四组文本数据: "the weather is good", "today is good", "good weather is ...

  9. 【Java】-NO.16.EBook.4.Java.1.008-【疯狂Java讲义第3版 李刚】- 集合/容器

    1.0.0 Summary Tittle:[Java]-NO.16.EBook.4.Java.1.008-[疯狂Java讲义第3版 李刚]- 集合 Style:EBook Series:Java Si ...

随机推荐

  1. 了解SELlinux

    selinux是mac: mandatory access control. 强制访问控制. 是经过了20年的mac研究基础上开发的安全子系统. 访问控制分为三种: dac: di'scretiona ...

  2. pycharm中git配置(coding.net为例)

    1.在coding.net注册一个账号 2.登陆coding.net 3.新建项目->输入项目名称.项目描述->初始化仓库选择readme.md并且添加一个appachev2的开源许可证- ...

  3. MongoDB 基本命令备忘

    使用admin数据库: use admin 显示数据库: show dbs 创建用户,并制定该用户的角色: db.createUser({user: "root",pwd:&quo ...

  4. VMware 虚拟化编程(13) — VMware 虚拟机的备份方案设计

    目录 目录 前文列表 备份思路 备份算法 备份细节 连接到 vCenter 还是 ESXi 如何选择快照类型 是否开启 CBT 如何获取备份数据 如何提高备份数据的传输率 备份厚置备磁盘和精简置备磁盘 ...

  5. 监测工具dstat使用说明

    参考地址: https://blog.csdn.net/sinat_34789167/article/details/80986709

  6. MongoDB优化心得分享

    这里总结下这段时间使用mongo的心得,列出了几个需要注意的地方. 1. 系统参数及mongo参数设置 mongo参数主要是storageEngine和directoryperdb,这两个参数一开始不 ...

  7. C#扩展方法 DataTable.ToEntitys

    类A需要添加功能,我们想到的就是在类A中添加公共方法,这个显而易见肯定可以,但是由于某种原因,你不能修改类A本身的代码,但是确实又需要增加功能到类A中去,怎么办? 这个时候扩展方法(Extension ...

  8. Appium-入门实例1

    参考:(https://blog.csdn.net/zh175578809/article/details/76862590) 第一步:启动虚拟设备 在运行App之前,首先需要创建一个Android模 ...

  9. linux文件io与标准io

    文件IO实际是API,Linux对文件操作主要流程为:打开(open),操作(write.read.lseek),关闭(close). 1.打开文件函数open(): 涉及的头文件:  #includ ...

  10. [Python3 填坑] 011 元组中有多个最值,索引出来的是哪一个

    目录 1. print( 坑的信息 ) 2. 开始填坑 (1) max() (2) min() (3) 结论 1. print( 坑的信息 ) 挖坑时间:2019/01/11 明细 坑的编码 内容 P ...