存储双列数据,存储key-value对的数据 ----类似于高中讲的函数
key
:无序、不可重复,使用Set存储所有的key —>要求key所在类重写equals()方法和hashCode()方法key-value
构成了一个Entry对象。object put(Object key,object value)
:将指定 key-value添加到(或修改)到当前map对象中public void putTest(){ HashMap map = new HashMap(); //添加 map.put("A",'a'); map.put("B",'b'); map.put("C",'c'); map.put("D",'d'); map.put("E",'e'); System.out.println(map); //修改 map.put("A","aa"); System.out.println(map); }
输出
{A=a, B=b, C=c, D=d, E=e} {A=aa, B=b, C=c, D=d, E=e}
void putAll(Map m)
:将m中的所有 key-value对存放到当前map中public void test(){ HashMap map = new HashMap(); //添加 map.put("A",'a'); map.put("B",'b'); map.put("C",'c'); map.put("D",'d'); map.put("E",'e'); System.out.println(map); HashMap map1 = new HashMap(); map1.putAll(map); System.out.println(map1); }
输出:
{A=a, B=b, C=c, D=d, E=e} {A=a, B=b, C=c, D=d, E=e}
Object remove(Object key)
:移除指定key的key-value对,并返回valueSystem.out.println(map.remove("A")); System.out.println(map.remove("a")); System.out.println(map);
输出:
aa null {B=b, C=c, D=d, E=e}
void clear
:清空当前map中的所有数据map.clear(); System.out.println(map); System.out.println(map.size());
输出:
{} 0
Object get(Object key)
:获取指定key对应的value
System.out.println(map.get("D")); System.out.println(map.get("DD"));
d null
boolean containsKey(Object key)
:是否包含指定的key
System.out.println(map.containsKey("E")); System.out.println(map.containsKey("EE"));
true false
boolean containsValue(Object value)
:是否包含指定的value
System.out.println(map.containsValue("a")); System.out.println(map.containsValue('a')); System.out.println(map.containsValue("asbha"));
false true false
int size()
;返回map中的 key-value 的个数
System.out.println(map.size());
5
boolean isEmpty()
:判断当前map是否为空
System.out.println(map.isEmpty()); map.clear(); System.out.println(map.isEmpty());
false true
boolean equals(Object obj)
:判断当前map和参数对象obj是否相等
HashMap map1 = new HashMap(); //添加 map1.put("A",'a'); map1.put("B",'b'); map1.put("C",'c'); map1.put("D",'d'); map1.put("E",'e'); System.out.println(map.equals(map1)); HashMap map2 = new HashMap(); //添加 map2.put("A",'a'); map2.put("B",'c'); map2.put("C",'c'); map2.put("D",'d'); map2.put("E",'e'); System.out.println(map.equals(map2));
true false
Set keySet()
:返回所有key构成的Collection集合
Collection values()
:返回所有value构成的Collection集合
Set entrySet()
:返回所有key-value对构成的Set集合
HashMap map = new HashMap(); //添加 map.put("A",'a'); map.put("B",'b'); map.put("C",'c'); map.put("D",'d'); map.put("E",'e'); //遍历 // `` Set keySet()``:返回所有key构成的Collection集合 Set set = map.keySet(); Iterator iterator = set.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } System.out.println("####"); // ``Collection values()``:返回所有value构成的Collection集合 Collection values = map.values(); for (Object obj : values){ System.out.println(obj); } System.out.println("####"); // ``Set entrySet()``:返回所有key-value对构成的Set集合 Set entrySet = map.entrySet(); Iterator iterator1 = entrySet.iterator(); while (iterator1.hasNext()){ Object obj = iterator1.next(); //entrySet集合中的元素都是entry Map.Entry entry = (Map.Entry) obj; System.out.println(entry.getKey() + "--->" + entry.getValue()); }
A B C D E #### a b c d e #### A--->a B--->b C--->c D--->d E--->e
作为Map的主要实现类
HashMap是线程不安全的,但是效率高
可以存储null的key或者value
HashMap底层:数组+链表(jdk7及以前),数组+链表+红黑树(jdk8)
保证在遍历Map元素时,可以按照添加的顺序实现遍历
原因:在原有的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素
对于频繁的遍历操作,此类执行效率高于HashMap
保证按照添加的key-value对进行排序,实现遍历排序。此时考虑key的自然排序,或者定制排序
底层使用红黑树
public void test1(){ TreeMap map = new TreeMap(); map.put("AA", 'a'); map.put(1,'c'); }
报错信息:
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
@Test public void test1(){ TreeMap map = new TreeMap(); User u1 = new User("Tom", 19); User u2 = new User("Alice", 51); User u3 = new User("Bob", 19); User u4 = new User("Jerry", 23); User u5 = new User("Jimi", 25); map.put(u1,98); map.put(u2,45); map.put(u3,65); map.put(u4,18); map.put(u5,54); Set entrySet = map.entrySet(); Iterator iterator1 = entrySet.iterator(); while (iterator1.hasNext()){ Object obj = iterator1.next(); //entrySet集合中的元素都是entry Map.Entry entry = (Map.Entry) obj; System.out.println(entry.getKey() + "--->" + entry.getValue()); } }
输出:
User{name='Tom', age=19}--->98 User{name='Jimi', age=25}--->54 User{name='Jerry', age=23}--->18 User{name='Bob', age=19}--->65 User{name='Alice', age=51}--->45
@Test public void test2(){ TreeMap map = new TreeMap(new Comparator() { @Override public int compare(Object o1, Object o2) { if(o1 instanceof User && o2 instanceof User){ User u1 = (User) o1; User u2 = (User) o2; return Integer.compare(u1.getAge(),u2.getAge()); } throw new RuntimeException("输入的类型不匹配"); } }); User u1 = new User("Tom", 19); User u2 = new User("Alice", 51); User u3 = new User("Bob", 19); User u4 = new User("Jerry", 23); User u5 = new User("Jimi", 25); map.put(u1,98); map.put(u2,45); map.put(u3,65); map.put(u4,18); map.put(u5,54); Set entrySet = map.entrySet(); Iterator iterator1 = entrySet.iterator(); while (iterator1.hasNext()){ Object obj = iterator1.next(); //entrySet集合中的元素都是entry Map.Entry entry = (Map.Entry) obj; System.out.println(entry.getKey() + "--->" + entry.getValue()); } }
输出:
User{name='Tom', age=19}--->65 User{name='Jerry', age=23}--->18 User{name='Jimi', age=25}--->54 User{name='Alice', age=51}--->45
作为古老的实现类
线程安全,但是效率低
不能存储null的key或者value
常用来处理配置文件。key和value都是String类型
应用场景
配置文件jdbc.properties
name=Tom password=abc123
java文件
public static void main(String[] args) { FileInputStream fis = null; try { Properties pros = new Properties(); fis = new FileInputStream("jdbc.properties"); pros.load(fis);//加载对应的文件 String name = pros.getProperty("name"); String password = pros.getProperty("password"); System.out.println("name = " + name + ",password = " + password); }catch (IOException e){ e.printStackTrace(); }finally { if(fis != null){ try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
输出:
name = Tom,password = abc123
# 四、Map相关面试题 ## 4.1 HashMap底层实现原理? ### jdk7 ```javascript HashMap map = new HashMap(); //在实例化后,底层创建了长度是16的一维数组Entry[] table
map.put(key1,value1); //首先计算key1所在类的hashCode方法计算key1哈希值,此哈希值结果某种计算后得到在Entry数组中的存放位置 //如果此位置上的数据为空,此时的key1-value1 添加成功 //如果此位置上的数据不为空,(意味着,此位置上,存在一个或多个数据(以链表的形式存在)),比较key1和已经存在的数据的哈希值: //如果key1的哈希值与已经存在的数据的哈希值都不同,此时key1-value1就添加成功 //如何key1的哈希值和已经存在的某一个数据(key2-value2)的哈希值相同,继续比较:调用key1所在类的equals(key2)方法比较: //如何返回false:此时key1-value1添加成功 //如果返回true:使用value1替换value2 // //
不断地添加过程中,会涉及到扩容问题,默认的扩容方式:扩容为原来容量的2倍,并将原有的数据复制过来
Node[]
,而非Entry[]put
方法时,底层创建长度为16的数组数组+链表
。jdk8中底层结构:数组+链表+红黑树
new HashMap()//底层没有创建一个长度为16的数组