JavaSE核心API--查找表Map与散列表HashMap
java.util.Map等
1)理论讲解:重写key元素的hashCode方法和equals方法
HashMap是当今查询速度最快的数据结构---因为HashMap可以根据key元素的hashCode方法返回该元素在散列表内部数组的下标位置,从而可以不用遍历而直接
找到该元素
但是作为key元素的hashCode方法和equals方法的实现如果不妥当,就会降低散列表的查询性能
-----所以要妥善重写key元素的hashCode方法和equals方法,可以尽量避免出现链表
在HashMap中出现链表就会影响其查询性能,而出现链表的一个主要原因:
当两个key元素的hashCode值(hashCode方法返回的数字)相同时,但它们equals比较不为true的时候,则会在HashMap内部形成链表
hashCode决定该元素在HashMap内部数组的下标位置
equals方法决定HashMap是否认为这两个key为重复
hashCode方法与equals方法是Object定义的方法,这两个方法在API手册的Object类中有明确的说明:
当我们需要重写一个类的equals或hashCode方法时要遵循下面几点要求:
1.成对重写,当我们重写一个类的equals方法时就应当连同重写hashCode,反过来也一样
2.一致性,当两个对象equals比较为true时,hashCode方法返回的数字必须相等,反过来则不是必须的,
但是尽量保证当两个对象hashCode相同时equals比较也为true
3.稳定性,当一个对象参与equals比较的属性值没有发生过改变的前提下,多次调用hashCode方法返回的数字应当不变(而不是返回随机数)
代码演示:
public class Key {
private int x;
private int y;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Key other = (Key) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}
2)理论讲解:Map与HashMap
java.util.Map查找表
Map的结构是一个多行两列的表格,其中左列称为key,右列称为value
Map总是以key-value对的形式保存数据,并且总是以key来获取对应的value
所以我们经常将要查询的数据作为value,将查询条件作为key,保存在Map中以便于根据条件快速查找对应的数据
java.util.HashMap散列表
HashMap是Map最常用的实现类,也是当今最快的查询结构
代码演示
public static void main(String[] args) {
/*
* Map要求指定两个泛型,分别说明key与value的类型
*/
Map<String, Integer> map = new LinkedHashMap<>();// 内部数组初始个数为16,当元素占够四分之三数组就要扩容
/*
* V put(K k,V v)
* 将给定的键值对保存到Map中
* 注:
* Map有一个要求,即Map中的key不允许重复,重复的标准是依靠key自身的equals比较结果
* 所以put方法是有返回值的,若本次存放的key已经在Map中存在,则是替换value操作,那么返回值就是被替换的value,否则为null
*/
/*
* 若value的类型为包装类,切记不要用对应的基本类型接受put方法的返回值
* 因为这会触发包装类自动拆箱,而put方法返回值有可能是null,这时若拆箱会发生空指针异常
*/
map.put("语文", 99);
map.put("数学", 98);
map.put("英语", 97);
map.put("物理", 96);
map.put("化学", 99);
System.out.println(map);
/** 若本次存放的key已经在Map中存在,则是替换value操作,那么返回值就是被替换的value,否则为null */
Integer num = map.put("语文", 77);
System.out.println(map);
System.out.println(num);
/*
* V get(Object key)
* 根据给定的key获取对应的value,若给定的key在Map中不存在则返回值为null
*/
num = map.get("英语");
System.out.println("英语:" + num);
num = map.get("体育");
System.out.println("体育:" + num);
int size = map.size();
System.out.println("size:" + size);
/*
* V remove(K k)
* 根据给定的key删除对应的这组键值对,返回值为该键值对中的value
*/
num = map.remove("物理");
System.out.println(map);
System.out.println(num);
/*
* boolean containsKey(Object k)
* boolean containsKey(Object v)
* 判断当前Map是否包含给定的key或value 包含的判断还是依靠元素自身equals比较的结果
*/
boolean ck = map.containsKey("语文");
boolean cv = map.containsValue(98);
System.out.println("是否包含key:" + ck);
System.out.println("是否包含value:" + cv);
}
3)理论讲解:Map的遍历
Map的遍历三种方式:
1.遍历所有的key
2.遍历所有key-value对
3.遍历所有的value(相对不常用)
代码演示:
public static void main(String[] args) {
// Map<String, Integer> map = new HashMap<>();
/*
* LinkedHashMap是可以做到遍历顺序与put时的顺序一致的
*/
Map<String, Integer> map = new LinkedHashMap<>();
map.put("语文", 99);
map.put("数学", 98);
map.put("英语", 97);
map.put("物理", 96);
map.put("化学", 99);
System.out.println(map);
/*
* 遍历所有的key Set keySet() 将当前Map中所有的key以一个Set集合形式返回 遍历该集合就等同于遍历了所有的key
*/
Set<String> keySet = map.keySet();
for (String key : keySet) {
System.out.println("key:" + key);
}
/*
* 遍历每组键值对 Set entrySet() 将当前Map中每组键值对(若干个Entry实例)以一个Set集合形式返回
*
* java.util.Map.Entry 每个Entry实例表示Map中的一组键值对 常用方法: K getKey():获取其表示的键值对中的key V
* getValue():获取其表示的键值对中的value
*/
Set<Entry<String, Integer>> entrySet = map.entrySet();
for (Entry<String, Integer> entry : entrySet) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + ":" + value);
}
/*
* 遍历所有的value Collection values() 将当前Map中所有的value以一个集合形式返回
* 由于Map中不要求value不重复,所以其不以Set集合形式返回
*/
Collection<Integer> values = map.values();
for (Integer value : values) {
System.out.println("value:" + value);
}
}
4.小练习:统计字符串中每个字符出现的次数
public static void main(String[] args) {
String str = "helloworld!this is java!i love java!";
Map<Character, Integer> map = new HashMap<>();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (map.containsKey(c)) {// 如果字符c存在则表明该字符出现过
int num = map.get(c);
num = num + 1;
map.put(c, num);
} else {// 否则就添加到map中,个数为1
map.put(c, 1);
}
}
System.out.println(map);
}