ht-4 hashmap特性
一、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特性的更多相关文章
- hashMap 底层原理+LinkedHashMap 底层原理+常见面试题
1.源码 java1.7 hashMap 底层实现是数组+链表 java1.8 对上面进行优化 数组+链表+红黑树 2.hashmap 是怎么保存数据的. 在hashmap 中有这样一个结构 ...
- ysoserial分析【二】7u21和URLDNS
目录 7u21 gadget链分析 hashCode绕过 参考 URLDNS 7u21 7u21中利用了TemplatesImpl来执行命令,结合动态代理.AnnotationInvocationHa ...
- YsoSerial 工具常用Payload分析之URLDNS
本文假设你对Java基本数据结构.Java反序列化.高级特性(反射.动态代理)等有一定的了解. 背景 YsoSerial是一款反序列化利用的便捷工具,可以很方便的生成基于多种环境的反序列化EXP.ja ...
- Leetcode分类刷题答案&心得
Array 448.找出数组中所有消失的数 要求:整型数组取值为 1 ≤ a[i] ≤ n,n是数组大小,一些元素重复出现,找出[1,n]中没出现的数,实现时时间复杂度为O(n),并不占额外空间 思路 ...
- SpringMVC无法获取请求中的参数的问题的调查与解决(2)
由于Request的getInputSteam()一旦获取一次后,就再也无法获取了 在实际项目中导致下面的问题: 1,多个拦截器,Filter都需要从InputStream中拿数据的情况无法处理: 2 ...
- Java中的集合类
实线边框的是实现类,比如ArrayList,LinkedList,HashMap等 折线边框的是抽象类,比如AbstractCollection,AbstractList,AbstractMap等, ...
- AnnotationUtils
/** * 查询类中符合指定annotation的属性信息 * @param objCls 实体类 * @param annCls 注解类 * @return HashMap<实体属性名, An ...
- MapReduce并行编程模型和框架
传统的串行处理方式 有四组文本数据: "the weather is good", "today is good", "good weather is ...
- 【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 ...
随机推荐
- leetcode 52 N皇后问题 II
51的简化版,省去根据排列话棋盘的工作,直接计数,代码: class Solution { public: int totalNQueens(int n) { ; vector<); dfs(n ...
- 记2018最后一次问题诊断-Spark on Yarn所有任务运行失败
2018的最后一个工作日,是在调式和诊断问题的过程中度过,原本可以按时下班,毕竟最后一天了,然鹅,确是一直苦苦挣扎. 废话不多说,先描述一下问题:有一套大数据环境,是CDH版本的,总共4台机子,我们的 ...
- 【AndroidFramework】ATV9遥控器红外模式下,机顶盒在假待机阶段会响应遥控器语音键
[问题描述] 测试部反馈,红外模式下,按power键进入假待机,按红外语音键会唤醒. 背景交代:红外语言键是我们自定义的按键,键值225.在红外模式下按会弹提示框"没连蓝牙,请连蓝牙使用语音 ...
- 【ABAP系列】SAP VA01屏幕增强(user-exit)
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP VA01屏幕增强(user- ...
- spring data jpa 使用SQL语句查询
package com.ytkj.entity; import javax.persistence.*; import java.io.Serializable; /** * @Entity * 作用 ...
- 第一次Java学习总结
初学Java感觉还是蛮可以的,可是做起题目来还是不能得心应手,自己不懂得太多太多,还是需要不断努力去学啊!下面我就把这些天学到的知识点总结一下: 初学Java,我把目前所学知识点总结如下: 1.jav ...
- [Python3 练习] 003 货币转换
题目:货币转换 (1) 描述 人民币和美元是世界上通用的两种货币,写一个程序进行货币间币值转换 记人民币和美元之间的汇率为:1 美元 = 6.78 人民币 程序可以接受人民币或美元输入,转换为另一种货 ...
- hdu-2389.rain on your parade(二分匹配HK算法)
Rain on your Parade Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 655350/165535 K (Java/Ot ...
- jvm学习(2)JVM内存说明
前言 一.类方法 类方法是静态方法,前面需要有static修饰符修饰.类方法内不能涉及有关变量的内容1.不能调用类的对象方法2.不能引用对象变量3.类方法不能被重写(覆盖)4.类方法不能使用super ...
- TimeUnit类 java.util.concurrent.TimeUnit
TimeUnit是什么? TimeUnit是java.util.concurrent包下面的一个类,表示给定单元粒度的时间段 主要作用 时间颗粒度转换 延时 常用的颗粒度 TimeUnit.DAYS ...