Map接口(高性能查找)、HashMap

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、实现步骤

  1. 导入一个Entry类型 import java.util.Map.Entry;
  2. 利用entrySet() 方法,将Map存储到一个Set集合中
    其中Set每个元素是一个Entry
  3. 对Set集合进行遍历处理,遍历时的Set元素是Entry类型
  4. 每个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类型注意事项

  1. key的类型:
    引用类型要求必须很好的成对重写了hashCode和equals方法
    java提供的引用类型一般都很好的重写了 (如:String、Integer)
  2. value可以是任何引用类型
    不能放基础类型,可以放其对应的包装类或者数组类型(int[])
  3. 如果不很好的成对重写key的hashCode和equals方法,会造成散列表工作异常
  4. 如果使用String作为key,总是没有问题的
  5. 开发工具提供了自动成对重写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;
	}
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值