java基础-Map集合
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.Map集合概述
我们通过查看Map接口描述,发现Map接口下的集合与Collection接口下的集合,它们存储数据的形式不同,如下:
1>.Collection中的集合,元素是孤立存在的,向集合中存储元素采用一个个元素的方式存储;
2>.Map中的集合,元素是成对存在的,每个元素是成对存在的,每个元素由键和值两部分组成,通过键可以找到对应的值;
3>Collection中的集合称为单列集合,Map中的集合称为双列集合;
4>.需要注意的是,Map中的集合不能包含重复的键,值可以重复;每个键只能对应一个值;
5>.Map中常用的集合为HashMap集合,LinkHashMap集合;
6>.Map存储元素使用put方法,Collection使用add发明合法;
7>.Map集合没有直接取出元素的方法,而是先转成Set集合,再通过迭代获取元素;
8>.Map集合中键要保证唯一性;
二.Map接口中常用集合概述
通过查看Map接口描述,看到Map有多个子类,我们Map集合常用类大概分为以下几种:
1>.Hashtable
线程安全,速度慢,不允许存放null键和null值,已被HashMap替代。
2>.HashMap
线程不安全,速度块,允许存放null键和null值。
3>.LinkedHashMap
Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。是HashMap的链表实现(可以用IDE查看源码),由哈希表保证了键的唯一性,由链表保证了元素的存取顺序。
4>.TreeMap
对键进行排序,排序原理 与TreeSet相同。
注意:Map接口中的结合都有两个泛型变量<K,V>,在使用时,要为两个泛型变量赋予数据类型。两个泛型变量<K,V>的数据类型可以相同,也可以不同。
三.Map接口中的常用方法
1>.V put(K,V)方法【将键值对存储到集合中,K作为键的对象,V作为值的对象】
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 7 package cn.org.yinzhengjie.note3; 8 9 import java.util.HashMap; 10 import java.util.Map; 11 12 public class MapDemo { 13 public static void main(String[] args) { 14 Map<String, Integer> map = new HashMap<>(); 15 Integer i = map.put("a", 100); //第一次存储,返回值为空 16 System.out.println(i); 17 i = map.put("a", 200); //以及存在“a”这个key,因此不会写入,返回存在key所对应的value。 18 System.out.println(i); 19 map.put("b", 200); 20 map.put("c", 100); 21 map.put("d", 300); 22 System.out.println(map); 23 } 24 } 25 26 27 /* 28 以上代码执行结果如下: 29 null 30 100 31 {a=200, b=200, c=100, d=300} 32 */
2>.V get(K)方法【通过键对象,获取值对象】
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 7 package cn.org.yinzhengjie.note3; 8 9 import java.util.HashMap; 10 import java.util.Map; 11 12 public class MapDemo { 13 public static void main(String[] args) { 14 Map<Integer, String> map = new HashMap<>(); 15 map.put(1, "yinzhengjie"); 16 map.put(2, "尹正杰"); 17 map.put(3, "2018"); 18 System.out.println(map); 19 String res = map.get(5); //如果key在map中不存在就返回空 20 System.out.println(res); 21 res = map.get(2); //如果key在map中存在就返回具体的value 22 System.out.println(res); 23 } 24 } 25 26 27 /* 28 以上代码执行结果如下: 29 {1=yinzhengjie, 2=尹正杰, 3=2018} 30 null 31 尹正杰 32 */
3>.V remove(K)方法【根据指定的键删除元素,返回被删除元素的值】
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 7 package cn.org.yinzhengjie.note3; 8 9 import java.util.HashMap; 10 import java.util.Map; 11 12 public class MapDemo { 13 public static void main(String[] args) { 14 Map<Integer, String> map = new HashMap<>(); 15 map.put(1, "yinzhengjie"); 16 map.put(2, "尹正杰"); 17 map.put(3, "2018"); 18 String res = map.remove(3); 19 System.out.println(res); 20 res = map.remove(4); 21 System.out.println(res); 22 System.out.println(map); 23 } 24 } 25 26 27 /* 28 以上代码执行结果如下: 29 2018 30 null 31 {1=yinzhengjie, 2=尹正杰} 32 */
4>.int size()方法【返回的是map集合中的长度】
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 7 package cn.org.yinzhengjie.note3; 8 9 import java.util.HashMap; 10 import java.util.Map; 11 12 public class MapDemo { 13 public static void main(String[] args) { 14 Map<Integer, String> map = new HashMap<>(); 15 map.put(1, "yinzhengjie"); 16 map.put(2, "尹正杰"); 17 map.put(3, "2018"); 18 int lenth = map.size(); 19 System.out.println(lenth); 20 } 21 } 22 23 24 /* 25 以上代码执行结果如下: 26 3 27 */
四.Map集合遍历方式
1>.KeySet方法
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 7 package cn.org.yinzhengjie.note3; 8 9 import java.util.HashMap; 10 import java.util.Iterator; 11 import java.util.Map; 12 import java.util.Set; 13 14 public class MapDemo { 15 public static void main(String[] args) { 16 Map<Integer, String> map = new HashMap<>(); 17 map.put(1, "yinzhengjie"); 18 map.put(2, "尹正杰"); 19 map.put(3, "2018"); 20 21 //调用map集合的方法keySet,所有的键存储到Set集合中 22 Set<Integer> set = map.keySet(); 23 //我们可以查看set类的全名,可以看出它是HashMap的内部类 24 System.out.println(set.getClass()); 25 //遍历set集合,获取出Set集合中的所有元素(Map中的键) 26 Iterator<Integer> it = set.iterator(); 27 while(it.hasNext()) { 28 //it.next()方法返回的是Set集合元素,也就是Map中的键 29 Integer key = it.next(); 30 //调用map集合的get方法,通过Map中的键获取其对应的value 31 String value = map.get(key); 32 System.out.println(key + "---" + value); 33 } 34 System.out.println("---$$$$$$$$$$$$$$$$$$$$$$$---"); 35 //增强for循环编译后其实还是迭代器形式,并且在写法上要比上面的写法要简单的多。 36 for (Integer key : map.keySet()) { 37 String value = map.get(key); 38 System.out.println(key + "---" + value); 39 } 40 } 41 } 42 43 44 /* 45 以上代码执行结果如下: 46 class java.util.HashMap$KeySet 47 1---yinzhengjie 48 2---尹正杰 49 3---2018 50 ---$$$$$$$$$$$$$$$$$$$$$$$--- 51 1---yinzhengjie 52 2---尹正杰 53 3---2018 54 */
2>.Map集合Entry对象
在Map类设计时,提供了一个嵌套接口:Entry。Entry将键值对的对应关系封装成了对象。即键值对对象,这样我们在遍历Map集合时,就可以从每一个键值对(Entry)对象中获取对应的键与对应的值。
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 7 package cn.org.yinzhengjie.note3; 8 9 import java.util.HashMap; 10 import java.util.Iterator; 11 import java.util.Map; 12 import java.util.Map.Entry; 13 import java.util.Set; 14 15 public class MapDemo { 16 public static void main(String[] args) { 17 Map<Integer, String> map = new HashMap<>(); 18 map.put(1, "yinzhengjie"); 19 map.put(2, "尹正杰"); 20 map.put(3, "2018"); 21 22 //调用map集合方法entrySet()将集合中的映射关系对象,存储到Set集合 23 Set<Map.Entry<Integer, String>> set = map.entrySet(); 24 //迭代Set集合 25 Iterator<Entry<Integer, String>> it = set.iterator(); 26 while(it.hasNext()) { 27 //获取出的Set集合的元素是映射关系,it.next()也是Map.Entry对象 28 Entry<Integer, String> entry = it.next(); 29 Integer key = entry.getKey(); 30 String value = entry.getValue(); 31 System.out.println(key+"---"+value); 32 } 33 System.out.println("###############################"); 34 //注意,增强for循环(foreach)不能遍历map!下面我遍历的是集合,并非是map哟!不要被面试官忽悠了 ! 35 for(Map.Entry<Integer,String> entry : map.entrySet()) { 36 System.out.println(entry.getKey() + "..." + entry.getValue()); 37 } 38 } 39 } 40 41 42 /* 43 以上代码执行结果如下: 44 1---yinzhengjie 45 2---尹正杰 46 3---2018 47 ############################### 48 1...yinzhengjie 49 2...尹正杰 50 3...2018 51 */
五.HashMap集合存储和遍历
1>.自定义类当value时常用遍历方式
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 7 package cn.org.yinzhengjie.note3; 8 9 public class Person { 10 private String Name; 11 private int Age; 12 public Person() { 13 super(); 14 } 15 public Person(String name, int age) { 16 super(); 17 Name = name; 18 Age = age; 19 } 20 public String getName() { 21 return Name; 22 } 23 public void setName(String name) { 24 Name = name; 25 } 26 public int getAge() { 27 return Age; 28 } 29 public void setAge(int age) { 30 Age = age; 31 } 32 }
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 7 package cn.org.yinzhengjie.note3; 8 9 import java.util.HashMap; 10 import java.util.Iterator; 11 import java.util.Map; 12 import java.util.Map.Entry; 13 import java.util.Set; 14 15 public class MapDemo { 16 public static void main(String[] args) { 17 HashMap<String, Person> map = new HashMap<>(); 18 map.put("beijing", new Person("yinzhengjie",18)); 19 map.put("西安", new Person("尹正杰",20)); 20 map.put("安康", new Person("邓西",25)); 21 System.out.println("第一种遍历方式:"); 22 for(String key : map.keySet()) { 23 Person value = map.get(key); 24 System.out.println("\t"+key + "..." + value); 25 } 26 System.out.println("第二种遍历方式:"); 27 for (Entry<String, Person> entry : map.entrySet()) { 28 String key = entry.getKey(); 29 Person value = entry.getValue(); 30 System.out.println("\t"+key + "..." + value); 31 } 32 } 33 } 34 35 36 /* 37 以上代码执行结果如下: 38 第一种遍历方式: 39 安康...cn.org.yinzhengjie.note3.Person@424c0bc4 40 beijing...cn.org.yinzhengjie.note3.Person@3c679bde 41 西安...cn.org.yinzhengjie.note3.Person@16b4a017 42 第二种遍历方式: 43 安康...cn.org.yinzhengjie.note3.Person@424c0bc4 44 beijing...cn.org.yinzhengjie.note3.Person@3c679bde 45 西安...cn.org.yinzhengjie.note3.Person@16b4a017 46 */
2>.自定义当key时常用遍历方式
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 7 package cn.org.yinzhengjie.note3; 8 9 public class Person { 10 private String Name; 11 private int Age; 12 public Person() { 13 super(); 14 } 15 public Person(String name, int age) { 16 super(); 17 Name = name; 18 Age = age; 19 } 20 public String getName() { 21 return Name; 22 } 23 public void setName(String name) { 24 Name = name; 25 } 26 public int getAge() { 27 return Age; 28 } 29 public void setAge(int age) { 30 Age = age; 31 } 32 @Override 33 public int hashCode() { 34 final int prime = 31; 35 int result = 1; 36 result = prime * result + Age; 37 result = prime * result + ((Name == null) ? 0 : Name.hashCode()); 38 return result; 39 } 40 @Override 41 public boolean equals(Object obj) { 42 if (this == obj) 43 return true; 44 if (obj == null) 45 return false; 46 if (getClass() != obj.getClass()) 47 return false; 48 Person other = (Person) obj; 49 if (Age != other.Age) 50 return false; 51 if (Name == null) { 52 if (other.Name != null) 53 return false; 54 } else if (!Name.equals(other.Name)) 55 return false; 56 return true; 57 } 58 59 }
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 7 package cn.org.yinzhengjie.note3; 8 9 import java.util.HashMap; 10 import java.util.Iterator; 11 import java.util.Map; 12 import java.util.Map.Entry; 13 import java.util.Set; 14 15 public class MapDemo { 16 public static void main(String[] args) { 17 HashMap<Person, String> map = new HashMap<>(); 18 map.put(new Person("dengxi",20),"里约热内卢"); 19 map.put(new Person("taotao",80),"索马里"); 20 map.put(new Person("fangheyi",30),"百慕大"); 21 map.put(new Person("yinzhengjie",65),"土耳其"); 22 map.put(new Person("yinzhengjie",65),"土耳其"); 23 System.out.println("第一种遍历方式:"); 24 for(Person key : map.keySet()) { 25 String value = map.get(key); 26 System.out.println("\t"+key + "..." + value); 27 } 28 System.out.println("第二种遍历方式:"); 29 for (Entry<Person, String> entry : map.entrySet()) { 30 Person key = entry.getKey(); 31 String value = entry.getValue(); 32 System.out.println("\t"+key + "..." + value); 33 } 34 } 35 } 36 37 38 /* 39 以上代码执行结果如下: 40 第一种遍历方式: 41 cn.org.yinzhengjie.note3.Person@3085b5e4...百慕大 42 cn.org.yinzhengjie.note3.Person@f90f1314...土耳其 43 cn.org.yinzhengjie.note3.Person@cb7d5231...索马里 44 cn.org.yinzhengjie.note3.Person@b0677c98...里约热内卢 45 第二种遍历方式: 46 cn.org.yinzhengjie.note3.Person@3085b5e4...百慕大 47 cn.org.yinzhengjie.note3.Person@f90f1314...土耳其 48 cn.org.yinzhengjie.note3.Person@cb7d5231...索马里 49 cn.org.yinzhengjie.note3.Person@b0677c98...里约热内卢 50 */
六.LinkedHashMap的特点
linkedHashMap继承自HashMap,可以保证迭代的顺序
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 7 package cn.org.yinzhengjie.note3; 8 9 import java.util.LinkedHashMap; 10 11 public class LinkedHashmapDemo { 12 public static void main(String[] args) { 13 LinkedHashMap<String,Integer> link = new LinkedHashMap<>(); 14 link.put("yinzhengjie", 18); 15 link.put("尹正杰", 18); 16 link.put("灵魂摆渡", 2018); 17 link.put("红海行动", 328); 18 link.put("神秘巨星",201712 ); 19 link.put("摔跤吧,爸爸",201705 ); 20 System.out.println(link); 21 } 22 } 23 24 /* 25 以上代码执行结果如下: 26 {yinzhengjie=18, 尹正杰=18, 灵魂摆渡=2018, 红海行动=328, 神秘巨星=201712, 摔跤吧,爸爸=201705} 27 */
七.Hashtable的特点
Map接口实现类Hashtable,底层数据结构依然是哈希表,特点和HashMap是一样的,HashMap线程不安全的集合,运行速度尽快,Hashtable命运和Vector是一样的,从JDK1.2开始,被更先进的HashMap取代。HashMap允许存储null值,null键,Hashtable不允许存储null值,null键。
尽管Hashtable虽然退出了历史舞台,但是它的孩子properties依然活跃在开发舞台,后期我们在说IO流是会详细介绍,这里就不介绍啦!我们可以看一下Hashtable存储null时抛出的空指针异常:
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 7 package cn.org.yinzhengjie.note3; 8 9 import java.util.Hashtable; 10 import java.util.Map; 11 12 public class HashtableDemo { 13 public static void main(String[] args) { 14 Map<String, String> map = new Hashtable<>(); 15 map.put(null, null); 16 System.out.println(map); 17 } 18 } 19 20 /* 21 以上代码执行结果如下: 22 Exception in thread "main" java.lang.NullPointerException 23 at java.base/java.util.Hashtable.put(Hashtable.java:475) 24 at cn.org.yinzhengjie.note3.HashtableDemo.main(HashtableDemo.java:15) 25 */
八.TreeMap的特点
基于树的Map,它的键唯一,并可以自动排序,根据使用的构造方法决定是使用元素本身可比性还是使用集合的可比性。
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 7 package cn.org.yinzhengjie.note3; 8 9 import java.util.TreeMap; 10 11 public class TreeMapDemo { 12 public static void main(String[] args) { 13 TreeMap<String, Integer> tree = new TreeMap<>(); 14 tree.put("yinzhengjie", 20); 15 tree.put("尹正杰", 18); 16 tree.put("Zhengjie", 20); 17 tree.put("BigData", 2018); 18 System.out.println(tree); 19 } 20 } 21 22 /* 23 以上代码执行结果如下: 24 {BigData=2018, Zhengjie=20, yinzhengjie=20, 尹正杰=18} 25 */