Java学习笔记(38)—— Map接口(HashMap)

这里将自己学习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被替换/覆盖了	
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值