一、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()

三、示例:

 package com.iotek.map;

 import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; public class HashMapDemo1 {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>(); // 接口的引用变量指向实现类的对象
// 创建HashMap对象,也就是创建一个Map容器
map.put(null, "张三"); // 添加键值对元素
map.put(null, "李四"); // 有相同的键时,后面添加的键对应的值会覆盖掉之前键对应的值
map.put("john", "李四");
map.put("rose", "玫瑰");
map.put("mary", "小红");
System.out.println("1" + map); // 获取map中所有键,返回的是一个Set容器,可以用迭代器对象或者foreach来进行输出
Set<String> keys = map.keySet();
System.out.println("******输出map容器中所有的键:");
for (String key : keys) {
System.out.print(key + " "); // 用String类型的变量key来遍历keys容器
} // 获取map中所有的值:使用map接口中的values方法,返回Collection接口的实现类
Collection<String> values = map.values();
System.out.println("\n******输出map容器中所有的值:");
for (String value : values) {
System.out.print(value + " "); // 用String类型的变量value来遍历values容器
} // 得到key的同时,得到key所对应的值
System.out.println("\n******用获取的键来得到对应的值并输出:");
for (String key : keys) {
System.out.print(key + "--" + map.get(key)); // 用String类型的变量key来遍历keys容器
}
System.out.println("\nmap容器中键值对的个数是:" + map.size());
System.out.println("判断map容器中是否为空:" + map.isEmpty()); // map.entrySet()返回的是一个set容器,其中放的是map.Entry内部接口
/*
* 当我们调用put(key,value)方法时,首先会把key和value封装到Entry这个静态内部类中,
* 再把Entry对象添加到数组中(哈希表),所以我们想要获取map中的所有键值对,只需要获取
* 数组汇总所有的Entry,接下来调用Entry对象中的getKey 和getValue方法就能获取键值对
* 以后想输出HashMap容器中所有的键值对,都可以调用HashMap的 entrySet()方法就可以了!!!
*/
Set<Entry<String, String>> entrys = map.entrySet();
System.out.println("使用map接口的entrySet()方法获取map容器中所有的键值对:");
for (Entry<String, String> entry : entrys) {
System.out.println(entry.getKey() + "-" + entry.getValue());
}
map.clear();
System.out.println("判断map容器中是否为空:" + map.isEmpty()); } }

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

 package com.iotek.map;

 import java.util.HashMap;
import java.util.Map; public class HashMapDemo2 { /**
* @param args
*/
public static void main(String[] args) {
Map<Student, String> map = new HashMap<Student, String>();
map.put(new Student("jay", 20), "张三"); //
map.put(new Student("lisi", 30), "李四");//
map.put(new Student("rose", 20), "玫瑰");//
map.put(new Student("lisi", 30), "陈飞");//
System.out.println(map.size());
System.out.println(map.toString()); /*
* Student类中不重写hashCode() and
* equals()方法,此处map.size()值是4,即map中有4个封装了键值对的Entry对象
* 重写了hashCode()和equals()方法后,2和4语句里的学生对象将被判断为同一个键名,因此2位置处的键值会被替换掉
* 这正是我们需要的,对象相同,应该判定为是同一个键,因此,这就是需要重写hashCode()和equals()方法的原因
*/
}
} class Student {
private String name;
private int age; @Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
/*
* 用source中的 Generate hashCode() and equals() 来 生成重写的hashCode()方法和equals()方法
* 只要姓名和年龄相同的学生,那么这个学生对象产生的hashCode值和equals方法的值也是一样的,
* 此时就可以认为是hashmap里放的是同一个对象,那么这两个相同的Student对象作为键时,
* 后面添加的Student对象对应的键值应该要覆盖掉前面添加的键值
*/ @Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true; // 只有当姓名和年龄都一样时,才返回一个true,表示是同一个对象
} public Student(String name, int age) {
super();
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 "Student [name=" + name + ", age=" + age + "]";
} }

结果:

使用hashmap判断数组中字符串出现的次数:
 package com.iotek.map;

 import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* 使用hashmap判断数组中字符串出现的次数
* @author Administrator
*
*/
public class AccountStringDemo { public static void main(String[] args) {
String[] strs = {"zhangsan","zhangsan","wangwu","chenliu","chenliu","lilei","lilei"};
Map<String,Integer> data = AccountUtil.account(strs);
AccountUtil.printData(data);
} } class AccountUtil {
public static Map<String,Integer> account(String [] strs) {
Map<String,Integer> data = new HashMap<String, Integer>();
for(int i = 0; i < strs.length; i++) {
String str = strs[i];
if(data.get(str) == null) {
data.put(str, 1);
//如果第一次统计到该字符串,将该字符串作为键名,其出现的次数作为键值,保存在map容器中
} else {
//如果不是第一次捕获到该字符串,则data.get(str)!=null,那么将键值加1,表示第二次读取到该字符串
data.put(str, data.get(str)+1);
}
}
return data; //将最终的hashmap容器,也就是data返回
} public static void printData(Map<String,Integer> data) {
//使用HashMap的EntrySet()方法,返回map容器:data中的所有键值对(全部封装在Entry中),然后进行打印
Set<Entry<String, Integer>> entrys = data.entrySet();
for(Entry<String, Integer> entry : entrys) {
System.out.println("字符串" + entry.getKey() + "出现了" + entry.getValue() + "次");
}
} }

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. 几个FFmpeg 视频参数 fps、tbr、tbn、tbc

    我们用Ffplay播放文件或者视频流命令行会出现fps.tbr.tbn.tbc等参数如下图所示 图1 ffplay 播放文件示意图 fps表示平均帧率,总帧数除以总时长(以s为单位). tbr  表示 ...

  2. AtomicInteger 源码分析

    AtomicInteger AtomicInteger 能解决什么问题?什么时候使用 AtomicInteger? 支持原子更新的 int 值. 如何使用 AtomicInteger? 1)需要被多线 ...

  3. 004-spring-data-elasticsearch 3.0.0.0使用【二】-spring-data之定义方法、创建repository实例、从聚合根发布事件

    续上文 1.4.定义方法 存储库代理有两种方法可以从方法名称派生特定于存储的查询.它可以直接从方法名称派生查询,或者使用手动定义的查询.可用选项取决于实际store.但是,必须有一个策略来决定创建什么 ...

  4. VMware 虚拟化编程(7) — VixDiskLib 虚拟磁盘库详解之三

    目录 目录 前文列表 VixDiskLib 虚拟磁盘库 VixDiskLib_GetMetadataKeys VixDiskLib_ReadMetadata 获取虚拟磁盘元数据 VixDiskLib_ ...

  5. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_06 Properties集合_2_Properties集合中的方法store

    第一行是注释,第二行是时间,时间是自动加的 使用FileOutputStream. 写入中文会乱码

  6. 四种方法给Vmware虚拟机清理瘦身

    随着VMware虚拟机使用时间的增长,其所占用的空间也越来越大,本文来说说怎么给VMware虚拟机占用的空间进行瘦身. **方法一:VMware自带的清理磁盘 **这个方法是VMware自带,具有普适 ...

  7. 几个模拟OLE事件注册、调用的宏

    最近遇到一个要求,将原来的OCX控件,替换成直接的DLL调用. 遇到OLE的事件回调,写了三个宏,用于简化代码 #define OLE_ENVENT_IN_CLASS_ONE(event_name, ...

  8. 04 bbed修复system文件头损坏

    04 bbed修复system文件头损坏 1 启动数据库,查看trace,在mount到open, SQL> startup mount; ORACLE instance started. To ...

  9. idea下载和设置自动翻译(有道)

    1:下载 点击file,点击settings,找到plugins,之后所搜translation并下载,他会自动从新启动idea 2:设置translation 3:这个应用ID和秘钥需要在有道智云去 ...

  10. vue—拖拽