Java基础 - Map 映射
一个接口,其目的是为了解决高性能查找问题。
实现Map接口的类都封装了高性能查找算法,利用Map接口的实现类就可以提高软件的查找性能,提供优秀的用户体。
Map的实现类HashMap是最快的查找算法(没有之一!最常用!非常快和储存容量无关)
Map的实现类TreeMap是比较快的查找算法
key:关键字(不可重复,若重复会替换原有的value,引用类型)
value:值(被查到的信息,可以重复,可以是任何引用类型)
HashMap(散列表、哈希表)
- 创建Map
Map<String,String> map = new HashMap<>();
- 将需要查询的数据,按照key-value储存到map对象中
map.put("key","value"); // put方法,将被查询的数据成对的添加到map中,
// 其中key是被检索的关键字,value是检索到的结果
- 查询使用的时候,根据key查询对应的value
map.get("key");
HashMap 查询性能
对比顺序查询
可以使用时间戳
System.currentTimeMillis() 毫秒
System.nanoTime() 纳秒
List<String> list = new ArrayList<>();
Map<String,String> map = new HashMap<>();
for(int i=1;i<=10000000;i++){
list.add("n"+i);
map.put("n"+i, i-1);
}
int i=0;
long t1 = System.nanoTime();
for(String s:list){
if(s.equals("n999999")){
break;
}
i++;
}
long t2 = System.nanoTime();
System.out.println(t2-t1);
long t3 = System.nanoTime();
int n = map.get("n999999");
long t4 = System.nanoTime();
System.out.println(t4-t3);
Map API
boolean map.put(key,value);
// 将key-value成对的添加到map中,如果map中已经有key了,则替换原有value
// 返回 被替换的value,若没有替换返回 null
Map<String,String> map = new HashMap<>();
String val = map.put("xxx","xxx");
map.get(key); // 用于再map中根据key检索value,返回值是检索到的value,
// 如果没有检索到,返回null
map.containsKey(key); // 由于map中允许value是null,所以检索到value为空的时候,返回null,
// 所以很难判断是否是存在key,因此使用此方法可以判断map中是否包含key
map.size(); // 返回key-value对的数量(int)
map.isEmpty(); // 检查集合是否为空(boolean)
map.remove(key); // 从map中删除,返回结果是删除key对应的value
map.clear() // 清空map集合
map遍历、迭代
Map<String,String> map = new HashMap<>();
map.put("xxx","xxx");...
Set<Entry<String,String>> set = map.entrySet(map); // 将map集合转成Set集合(因为Set集合中有iterator方法)
// 需要导入java.util.Map.Entry的Entry类型
// 因为map中存储对象是Entry接口,所以泛型要写Entry,但是
// Entry中也存在泛型,所以也要给Entry写泛型(key-value)
for(Entry<String,String> e : set){
String key = e.getKey();
String value = e.getValue();
}
HashMap问题
如果不很好的重写key的hashCode和equlas方法,会造成散列表工作异常
使用String作为key,总是可以的!
开发工具提供了自动成对重写hashCode和equals方法的功能
打麻将的例子:
// 位置
class Location{
String name;
public Location(String name){
this.name = name;
}
public String toString(){
return name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Location other = (Location) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
class Test{
public static void main(String[] args){
Map<Location,String> map = new HashMap<>();
map.put(new Location("东"),"张三");
map.put(new Location("西"),"李四");
map.put(new Location("南"),"王五");
map.put(new Location("北"),"赵六");
System.out.println(map); // {东:张三,西:李四,南:王五,北:赵六}
map.put(new Location("东"),"我");
System.out.println(map); // 若未重写类中的equals和HashCode => {东:张三,东:我,西:李四,南:王五,北:赵六}
// 重写 => {东:张三,西:李四,南:王五,北:赵六}
System.out.println(map.get("西")); // 若未重写类中的equals和HashCode => null
// 重写 => 李四
}
}