Java基础 - Map 映射

一个接口,其目的是为了解决高性能查找问题。
实现Map接口的类都封装了高性能查找算法,利用Map接口的实现类就可以提高软件的查找性能,提供优秀的用户体。

Map的实现类HashMap是最快的查找算法(没有之一!最常用!非常快和储存容量无关)
Map的实现类TreeMap是比较快的查找算法

key:关键字(不可重复,若重复会替换原有的value,引用类型)
value:值(被查到的信息,可以重复,可以是任何引用类型)

HashMap(散列表、哈希表)

  1. 创建Map
Map<String,String> map = new HashMap<>();
  1. 将需要查询的数据,按照key-value储存到map对象中
map.put("key","value");	// put方法,将被查询的数据成对的添加到map中,
						// 其中key是被检索的关键字,value是检索到的结果
  1. 查询使用的时候,根据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
												// 重写 => 李四
		}
	}