这里将自己学习java及其应用的一些笔记、积累分享一下
一、HashMap
1.1 概述
- HashMap称之为哈希表,或散列表
- HashMap存放“键值对”数据,例如:
- 哈希表的作用:
用键,快速定位数据,提取对应的值
s = map.get(9527)
- 键:
不重复
无序
1.2 方法
- put(key, value)
放入键值对数据
放入重复的键,会用新值替换旧值
- get(key)
提取指定键对应的值
若键不存在,得到 null 值
- remove(key)
移除一对数据,并返回被移除的值
- size()
- ketSet()
把map中所有的key取出,并存入一个Set类型的集合中
1.2.1 练习:HashMap自带方法测试
package 测试HashMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
/*
* HashMap方法测试
*/
public class Test1_HashMap自带方法测试 {
public static void main(String[] args) {
// 新建hashmap对象
HashMap<Integer, String> map = new HashMap<Integer, String>();
// 添加数据
map.put(1, "盖聂");
map.put(2, "卫庄");
map.put(3, "赤练");
map.put(4, "白凤");
map.put(5, "玉麒麟");
map.put(6, "无双");
map.put(6, "鬼谷子");
map.put(7, null);// key和value都支持null
map.put(null, "---"); // null默认排在key的最前面
System.out.println(map.size()); // 返回Map的数据个数
System.out.println(map);
System.out.println(map.get(4));// 返回Key=4的数据
System.out.println(map.get(99));// 不存在的key返回null
System.out.println(map.remove(1));// 删除key=1的键值对,并返回value
System.out.println(map);
/*
* map.keyset()
* 把所有的key取出来创建成一个Set类型的集合
*/
Set<Integer> kset = map.keySet();
// 迭代器遍历集合-- for + alt + /
for (Iterator it = kset.iterator(); it.hasNext();) {
Integer key = (Integer) it.next();
System.out.println(key);
}
// for-each简化的遍历集合
for(Integer key : kset) {
System.out.println(key);
System.out.println(map.get(key));;
}
}
}
1.2.2 练习:字符串的字符统计
这个例子,我们编写一个字符串中的字符统计的案例,其实现的内容如下:
给定一个字符串"abacded" ,可以统计出该字符串中出现了哪些字符以及它们的出现频次
key value
a 2
b 1
c 1
package 测试HashMap;
// hashmap应用实例
import java.util.HashMap;
import java.util.Scanner;
public class Test2_字符串中的字符统计 {
public static void main(String[] args) {
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
System.out.println("请任意输入一串字符串:");
String s = new Scanner(System.in).nextLine();
// 根据s.length()遍历每一个字符,统计出现次数
for(int i = 0;i<s.length();i++) {
char tmp = s.charAt(i);
// 判断map中是否存在该key
if(map.get(tmp)!=null) {
map.put(tmp, map.get(tmp)+1);//map中已存在该key,则value+1
}else {
map.put(tmp, 1);// map中不存在该key,则作为新键值对写入
}
}
System.out.println("字符统计结果如下:");
System.out.println(map);
}
}
1.3 哈希运算过程
- HashMap内部使用 Entry[] 数组存放数据,数组默认初始长度 16
- 可以通过调用 key.hashCode() 方法获得一个哈希值。hashCode()方法是Object类型自带的,默认用对象内存地址作为哈希值,可根据具体需求,进行重写。
- 用哈希值和数组长度,计算数据存入Entry[]数组时的下标 i
- 键值对要封装成 Entry 对象
- Entry 对象放入Entry[]数组 i 位置时:
1. 若有空位置,则直接放入
2. 若有数据,依次用 equals() 比较是否相等。equals()方法是Object类型自带的,默认比较内存地址,可根据具体需求,进行重写。
2.1 若找到相等的,则用新的值替换旧的值
2.2 若没有相等的,则通过链表将 i 位置的所有数据(包括新旧值)连接在一起
3. Entry[]数组负载率、加载因子 到 0.75
3.1 数据量/数组容量 到 75%时,新建容量翻倍的新数组。完成新建后,所有数据,重新执行哈希运算,得到新的下标 i ,放入新数组对应位置存储
4. jdk1.8 新特性
对于Entry[]数组中,某一下标 i 存储的多个数据,当:
4.1 链表长度到8,会转成红黑树
4.2 树上数据减少到6,会转回成链表
- hashCode()
是 Object 的方法
默认实现:使用内存地址作为哈希值
1.3.1 练习:坐标点与销售额
package 哈希算法;
public class Point {
private int x;
private int y;
public Point() {
super();
}
public Point(int x, int y) {
super();
this.x = x;
this.y = y;
}
// 重写equals()确保相同的数据,其euqals返回true
@Override
public boolean equals(Object obj) {
if(obj instanceof Point) {
Point p = (Point) obj;
return this.x==p.x && this.y==p.y;
}
return false;
}
// 重写hashCode()确保相同的key,其哈希值相同
/*
* 希望相同的x,y值就要有相同的hash值
* 哈希算法要让hash值尽量分散
*/
@Override
public int hashCode() {
/*
* 数学家发明了一种算法可以让哈希值尽量的分散
*/
int p = 31;// 不可变
int r = 1;// 值任意
r= r*p +x;
r = r*p +y;
return r;
}
@Override
public String toString() {
return "("+this.x+","+this.y+")";
}
public int getX() {
return this.x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return this.y;
}
public void setY(int y) {
this.y = y;
}
}
package 哈希算法;
import java.util.HashMap;
/*
* key value
* 坐标点 -- 销售额
* [1,3] -- "2.9亿"
* [1,3] -- "3.0亿",覆盖
*
*/
public class Test1 {
public static void main(String[] args) {
Point a = new Point(1, 3);
Point b = new Point(1, 3);
/*
* 哈希运算
* k.hashCode()得到哈希值,用哈希值与数组容量计算下标
*
* 哈希值相同,才能保证计算出相同位置
*/
// 默认的hashCode()方法继承于Object,其比较的是内存地址
System.out.println(a.hashCode() == b.hashCode());// Point类重写前是false
/*
* 即使计算出相同位置
* equals()也必须相同,才能保证计算出相同位置
*/
System.out.println(a.equals(b));// Point类重写前是false
HashMap<Point, String> map = new HashMap<Point, String>();
map.put(a, "2.9");
map.put(b, "3.0");
System.out.println(map); // 最终显示的是3.0,因为key相同,value被替换/覆盖了
}
}