Map接口(高性能查找)
Map介绍
Map 地图,对应,映射
Java 集合API中的Map是映射的意思
不建议翻译,直接说Map就行了
Map无序,为查找而设计,不用于存储数据
Map中的元素为key-value(键值对),也叫映射
Map是一个接口
其目的是为了解决高性能查找问题
实现Map接口的类,都封装了高性能查找算法
利用Map接口的实现类就可以提高软件的查找性能,提供优质的用户体验
HashMap (主要用这个)
是Map的实现类之一
是最快的查找算法,没有之一
查询的速度做到了与数据量无关
HashMap也叫散列表或者哈希表
TreeMap
是Map的实现类之一
是比较快的查找方法
HashMap的性能体现
HashMap的查询性能(对比顺序查询)
在list中存储n1、n2、n3、···、n1000000,利用for循环找到n999700的位置
package collection.map;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MapDemo2 {
public static void main(String[] args) {
//使用普通查询
List<String> list = new ArrayList<>();
for(int i=1;i<=1000000;i++){
list.add("n"+i);
}
//找到n999700
long t1 = System.nanoTime();//记录当前纳秒
int index = 0;
for(String s:list){
if("n999700".equals(s)){
break;
}
index++;
}
long t2 = System.nanoTime();
System.out.println("普通查询耗时"+(t2-t1)+"纳秒");
System.out.println("找到n999700在"+index+"位置");
//使用HashMap查询
Map<String,Integer> map = new HashMap<>();
for(int i=1;i<=1000000;i++){
map.put("n"+i, i-1);
}
long t3 = System.nanoTime();
int n = map.get("n999700");
long t4 = System.nanoTime();
System.out.println("HashMap查询耗时"+(t4-t3)+"纳秒");
System.out.println("找到n999700在"+n+"位置");
}
}
Map的常用API
先定义一个HashMap
Map<String, String> map = new HashMap<>();
1、添加元素(put)
V put(K key, V value)
向Map中按键值对添加元素
如果Map中已经有key了,则替换原有的value,返回被替换的value,
如果没有被替换,返回一个null
一般不接收返回值
String val1 = map.put("路遥", "平凡的世界");
String val2 = map.put("路遥", "人生");
System.out.println(val1);//没有被替换
System.out.println(val2);//替换了,返回原value
map.put("罗贯中", "三国演义");
map.put("施耐庵", "水浒传");
map.put("吴承恩", "西游记");
map.put("曹雪芹", "红楼梦");
System.out.println(map);
2、检索元素(get)
V get(Object key)
用于在Map中根据key检索value
返回值是检索到的value;如果没有检索到,返回null
由于map中允许value就是null,
所以就算检索到了,由于这个值是null,也会返回null
String val = map.get("路遥");
System.out.println(val);
//找的到但是值为null
map.put("弟弟", null);
val = map.get("弟弟");
System.out.println(val);
//找不到,返回null
val = map.get("爸爸");
System.out.println(val);
3、判断是否包含指定key(containsKey)
boolean containsKey(Object key)
检查Map中是否含有指定的key(contains包含的意思)
如果包含返回true,不包含返回false
boolean b = map.containsKey("路遥");
System.out.println("“路遥”在map中吗"+b);
b = map.containsKey("弟弟");
System.out.println("“弟弟”在map中吗"+b);
b = map.containsKey("爸爸");
System.out.println("“爸爸”在map中吗"+b);
4、查看Map长度大小(size)
int size() 返回键值对的数量
int n = map.size();
System.out.println("map中含有元素个数:"+n);
5、判断Map是否为空(isEmpty)
boolean isEmpty()
判断Map是否为空
如果不含任何键值对,返回true;如果含有键值对,返回false
System.out.println("map是否为空集:"+map.isEmpty());
6、删除键值对(remove)
V remove(Object key)
从Map集合中删除key对应的键值对(key和value都被删除)
返回被删除的value
boolean remove(Object key, Object value)
效果相同,返回值为是否成功删除,成功为true,反之为false
一般不用这个
String reVal = map.remove("路遥");
System.out.println("删除的值为:"+reVal);
boolean reb = map.remove("弟弟", null);
System.out.println("是否成功删除“弟弟”:"+reb);
System.out.println(map);
7、清空集合(clear)
void clear() 清空集合
map.clear();
System.out.println("map集合长度:"+map.size());
System.out.println("map集合是否为空:"+map.isEmpty());
Map的遍历
1、entrySet方法(将Map转换为Set)
Set<Map.Entry<K,V>> entrySet()
返回此Map中包含的映射的Set视图,即将Map类型转换为Set集合类型
注意:Set中写的泛型应该为Entry<T, T>
转换为的set集合中的元素类型为Entry
其语法格式为:接收返回值的Set集合 = Map调用entrySet方法返回的Set集合
Set<Entry<String,String>> set = map.entrySet();
Set、Entry和Map的关系:
一个Entry,就是一个键值对,即Map中的一个元素
一个Map,就是一个Set(转化为Set集合),即一个键值对数组(即一个List,包含多个Entry)
Set和Entry,一般在Map遍历的时候,才会用到,平时很少用
2、实现步骤
- 导入一个Entry类型 import java.util.Map.Entry;
- 利用entrySet() 方法,将Map存储到一个Set集合中
其中Set每个元素是一个Entry - 对Set集合进行遍历处理,遍历时的Set元素是Entry类型
- 每个Entry对象包含两个方法
getkey:获取Entry对象的key
getvalue:获取Entry对象的value
package collection.map;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class MapDemo4 {
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("罗贯中", "三国演义");
map.put("施耐庵", "水浒传");
map.put("吴承恩", "西游记");
map.put("曹雪芹", "红楼梦");
map.put("路遥", "平凡的世界");
//输出全部作者及其书籍
System.out.println(map);
//Map转换为Set集合
Set<Entry<String,String>> set = map.entrySet();
System.out.println(set);
//现在可以通过Iterator(迭代器)遍历Set
//使用增强for循环遍历Set
for(Entry<String, String> e: set){
//getKey()获取key(作者)
String author = e.getKey();
//getValue()获取value(书籍)
String books = e.getValue();
System.out.println("作者:"+author+",书籍:"+books);
}
}
}
key与value的类型限制
key-value,也叫做键值对、映射
是Map中的构成元素
Map中的key类型、value类型注意事项
- key的类型:
引用类型要求必须很好的成对重写了hashCode和equals方法
java提供的引用类型一般都很好的重写了 (如:String、Integer) - value可以是任何引用类型
不能放基础类型,可以放其对应的包装类或者数组类型(int[]) - 如果不很好的成对重写key的hashCode和equals方法,会造成散列表工作异常
- 如果使用String作为key,总是没有问题的
- 开发工具提供了自动成对重写hashCode和equals方法的快捷功能(shift+alt+s,然后看名字找)
package collection.map;
import java.util.HashMap;
import java.util.Map;
public class MapDemo5 {
public static void main(String[] args) {
//正确示范
//使用整数作为key,double作为value
Map<Integer,Double> map1 = new HashMap<>();
map1.put(1, 1.1);
map1.put(2, 2.2);
map1.put(3, 3.3);
map1.put(98, 98.89);
map1.put(99, 99.99);
map1.put(100, 100.001);
System.out.println(map1);
System.out.println(map1.get(98));
//错误示范
//使用自定义类Location作为key
Map<Location,String> map2 = new HashMap<>();
map2.put(new Location("东"), "曹长卿");
map2.put(new Location("南"), "邓太阿");
map2.put(new Location("西"), "徐凤年");
map2.put(new Location("北"), "拓跋菩萨");
System.out.println(map2);
//会添加两个“东”键值对
map2.put(new Location("东"), "王仙芝");
System.out.println(map2);
//输出结果:{西=徐凤年, 东=王仙芝, 东=曹长卿, 南=邓太阿, 北=拓跋菩萨}
//get也会获得一个null,因为new会创建新对象,equals默认比较引用地址
System.out.println(map2.get(new Location("南")));//null
}
}
/**
* 位置类
* 供测试不合理key类型使用
* @author Tian
*/
class Location{
String name;
public Location(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}