目录
12.4.2.Map集合第二种遍历方式:使用Entry对象来遍历
12.4.3.Map集合第三种遍历方式:JDK8新特性新增的lambda表达式遍历Map的方法——Map.forEach();
12.Map集合
- 能够说出Map集合特点
-
使用Map集合添加方法保存数据
-
使用“键值对”方式遍历Map集合
-
使用HashMap存储自定义键值对的数据
-
能够使用HashMap编写斗地主洗牌发牌案例
12.1.Map与Collection接口下的集合区别
1.Map集合也是一个工具,在java.util包中,它是一个接口,有两个泛型Map<K,V>,K表示键,V表示值。键唯一。
2.通过查看Map接口描述,发现Map接口下的集合与Collection接口下的集合,它们存储数据的形式不同:
1.Collection<E>接口定义了单列集合规范,该接口中的集合每次存储一个元素。单身接口。
2.Map<K,V>接口定义了双列集合的规范,该接口下的集合每个元素都有键与值两个部分组成。
3.Collection中的集合称为单列集合,Map中的集合称为双列集合。
12.2.Map接口特点
1.java.util.Map<k,v>集合
2:Map集合的特点:
1.Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)
2.Map集合中的元素,key和value的数据类型可以相同,也可以不同。
3.Map集合中的元素,key是不允许重复的(key唯一),value可以
4.Map集合中的元素,key和value是一一对应的。
12.3.Map接口常用方法
* Map接口中常用方法: * public V put(K key,V value):把指定的键与值添加到Map集合中 * public V remove(Object key):把指定的键所对应的键值对元素在Map集合中删除 * public V get(Object key):根据指定的键,在Map集合中获取对应的值 * boolean containsKey(Object key):判断集合中是否包含指定的键 * 1.public V put(K key,V value):把指定的键与值添加到map集合 * 返回值:v * 存储键值对的时候,key不重复,返回值v是null * 存储键值对的时候,key重复,会使用新的value替换map中重复的value, * 返回被替代的value值。 *2.public V remove(Object key):把指定的键所对应的键值对元素在Map集合中删除, * 返回被删除元素的值。 * 返回值:v * key存在,返回值v为被删除的值。 * key不存在,返回值v为null。 * 3.public V get(Object key):根据指定的键,在Map集合中获取对应的值 * 返回值:key存在,返回对应的value值 * key不存在,返回null * 4.boolean containsKey(Object key):判断集合中是否包含指定的键 * 包含返回true,否则false
public class Demo2_map { public static void main(String[] args) { // show01(); // show02(); //show03(); show04(); } //1.public V put(K key,V value):把指定的键与值添加到map集合 private static void show01(){ //创建Map集合对象,使用多态方式(接口来接收子类对象) Map<String,String> map=new HashMap<>(); String v1 = map.put("李晨", "范冰冰1"); System.out.println("v1:"+v1);//v1:null String v2 = map.put("李晨", "范冰冰2"); System.out.println("v2:"+v2);//v2:范冰冰1(键重复,返回被替代的值) System.out.println(map);//{李晨=范冰冰2} map.put("冷锋","龙小云"); map.put("杨过","小龙女"); map.put("伊志平","小龙女"); System.out.println(map); // {杨过=小龙女, 伊志平=小龙女, 李晨=范冰冰2, 冷锋=龙小云} } //2.public V remove(Object key):把指定的键所对应的键值对元素在Map集合中删除, private static void show02(){ //创建Map集合对象,多态方式 Map<String,Integer>map1=new HashMap<>(); map1.put("赵丽颖",168); map1.put("杨颖",165); map1.put("林志颖",178); System.out.println(map1);//{赵丽颖=168, 杨颖=165, 林志颖=178} Integer v1 = map1.remove("林志颖"); System.out.println("v1:"+v1);//v1:178 System.out.println(map1);//{赵丽颖=168, 杨颖=165} Integer v2 = map1.remove("林志玲"); System.out.println("v2:"+v2);//v2:null表示集合中没有该键值对 } //3.public V get(Object key):根据指定的键,在Map集合中获取对应的值 private static void show03(){ //创建map集合对象 Map<String,Integer>map2=new HashMap<>(); map2.put("赵丽颖",168); map2.put("杨颖",165); map2.put("林志颖",178); Integer v3 = map2.get("杨颖"); System.out.println("v3:"+v3);//v3:165 Integer v4 = map2.get("迪丽热巴"); System.out.println("v4:"+v4);//v4:null } //4.boolean containsKey(Object key):判断集合中是否包含指定的键 private static void show04(){ //创建map集合对象 Map<String,Integer>map3=new HashMap<>(); map3.put("赵丽颖",168); map3.put("杨颖",165); map3.put("林志颖",178); boolean b1 = map3.containsKey("赵丽颖"); System.out.println("b1:"+b1);//b1:true boolean b2 = map3.containsKey("赵颖"); System.out.println("b2:"+b2);//b2:false } }
12.4.遍历map三种方式
12.4.1.Map集合第一种遍历方式:键找值的方式
1.public Set<K> keySet():获取Map集合中所有的键,存储到Set集合中。
2.Map集合第一种遍历方式:键找值的方式
1.由map集合中的keySet()方法获取Map集合中所有的键,存储到Set集合中。
2.使用迭代器或增强for遍历Set集合,获取map集合中每一个key
3.再由map集合中get(key)方法获取map集合中每一个key对应的value.public class Demo3_map { public static void main(String[] args) { //创建Map集合对象,多态方式 Map<String,Integer>map=new HashMap<>(); map.put("赵丽颖",168); map.put("杨颖",165); map.put("林志颖",178); //1.由map集合中的keySet()方法获取Map集合中所有的键,存储到Set集合中 Set<String> set = map.keySet(); //2.使用迭代器或增强for遍历Set集合,获取map集合中每一个key Iterator<String> it = set.iterator(); while(it.hasNext()){ String key = it.next(); //3.再由map集合中get(key)方法获取map集合中每一个key对应的value. Integer value = map.get(key); System.out.println(key+"="+value); } System.out.println("............. ...."); //或者使用增强for来遍历Set集合 for (String key : set) {//简化for(String key:map.keySet()) //3.再由map集合中get(key)方法获取map集合中每一个key对应的value. Integer value = map.get(key); System.out.println(key+"="+value); } } }
12.4.2.Map集合第二种遍历方式:使用Entry对象来遍历
- 在 Map.Entry 接口中以下的方法最为常用:
1.public Set<Map.Entry<K,V>> entrySet():获取Map集合中所有键值对对象的集合(Set集合)
2.Map.Entry<K,V>:Map接口中的一个内部接口Entry
3.作用:当Map集合创建时,会在Map集合中创建一个Entry对象,用于封装Map集合中的一组键值(也叫键值对对象)
4.Map集合第二种遍历方式:使用Entry对象来遍历
1.由map集合中的Set<Map.Entry<K,V>> entrySet()方法,把map集合中多个Entry对象取出来存储到Set集合中。
2.遍历Set集合,获取Set集合中每一个Entry对象
3.由Entry对象中的方法getKey()和getValue()分别获取键与值public class Demo4_map { public static void main(String[] args) { //创建Map集合对象,多态方式 Map<String,Integer>map=new HashMap<>(); map.put("赵丽颖",168); map.put("杨颖",165); map.put("林志颖",178); /*1.由map集合中的Set<Map.Entry<K,V>> entrySet()方法, 把map集合中多个Entry对象取出来存储到Set集合中。 */ Set<Map.Entry<String,Integer>> set=map.entrySet();//创建set集合并接收对象 /*2.遍历Set集合,获取Set集合中每一个Entry对象*/ //2.1使用迭代器遍历set集合 Iterator<Map.Entry<String, Integer>> it = set.iterator();//创建迭代器 while(it.hasNext()){ Map.Entry<String, Integer> entry = it.next();//获取集合中entry对象 //3.由Entry对象中的方法getKey()和getValue()分别获取键与值 String key = entry.getKey(); Integer value = entry.getValue(); System.out.println(key+"="+value); } System.out.println("........................"); //2.2使用增强for遍历set集合 for (Map.Entry<String, Integer> entry : set) { //3.由Entry对象中的方法getKey()和getValue()分别获取键与值 String key = entry.getKey(); Integer value = entry.getValue(); System.out.println(key+"="+value); } } }
12.4.3.Map集合第三种遍历方式:JDK8新特性新增的lambda表达式遍历Map的方法——Map.forEach();
ublic static void main(String[] args) { Map<String,String> map = new HashMap<>(); map.put("1","飞机"); map.put("2","坦克"); map.put("3","大炮"); map.forEach((k,v)-> { System.out.println(k+":"+v); }); }
12.5.Map接口实现类_HashMap
12.5.1.HashMap存储结构和特点
- java.util.HashMap<K,V>集合 implements Map<K,V>接口
- HashMap集合底层是哈希表:查询速度特别快。
- jdk1.8之前,哈希表结构:数组+单向链表;jdk1.8之后,哈希表结构:数组+单向链表/红黑树(链表长度超过8)
- HashMap集合是一个无序的集合,key唯一(不重复)
12.5.1.HashMap存储自定义类型键值
12.5.2.Map集合如何保证key唯一(不重复)
- 若键key是自定义类型,那么该类型的类必须重写hashCode和equals方法,以保证唯一性(不重复)。
- 下面键key是String类型,不需要重写。
public class Demo5_Person { private String name; private int age; public Demo5_Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Demo5_Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } } /** * HashMap存储自定义类型键值 * Map集合保证key是唯一的方法:作为key的元素,必须重写hashCode方法和equals方法 * * 下面案例是演示键为String类型,已经默认重写了hashCode和equals方法,不需再重写。 * 值为Demo5_Person类型,属于自定义类型。不需要重写。 */ public class Demo5_map { public static void main(String[] args) { show01(); } /** * HashMap存储自定义类型键值 * key:String类型 * String类已经重写了hashCode和equals方法,因此可以保证key唯一。 * value:Demo5_Person类型(自定义) * value可以重复(即同名同年龄的人视为同一人) */ private static void show01(){ //创建HashMap集合,键值对中值类型是自定义的Person类型 HashMap<String,Demo5_Person> map = new HashMap<>(); //往集合添加元素 map.put("北京",new Demo5_Person("张三",18)); map.put("上海",new Demo5_Person("李四",19)); map.put("广州",new Demo5_Person("王五",20)); map.put("北京",new Demo5_Person("赵六",18)); //使用keySet和增强for遍历map集合 Set<String> set = map.keySet();//将map中所有key存入set集合 for (String key : set) { Demo5_Person person = map.get(key); System.out.println(key+":"+person); } /*上海:Person{name='李四', age=19} 广州:Person{name='王五', age=20} 北京:Person{name='赵六', age=18} */ //因为键key是String类型,该String类又默认重写了hashCode和equals方法, //因此上述存储的元素实现了key值唯一。 } }
- 下面键key是自定义类型,需重写hashCode和equals方法
* HashMap存储自定义类型键值 * Map集合保证key是唯一的方法:作为key的元素,必须重写hashCode方法和equals方法 * * 下面案例是演示键为Person类型,需要在Person类中重写hashCode方法和equals方法。 * 值为String类型,不需重写。(只要求key唯一) public class Demo6_Person { private String name; private int age; public Demo6_Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Demo6_Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Demo6_Person that = (Demo6_Person) o; return age == that.age &&Objects.equals(name, that.name); } @Override public int hashCode() { return Objects.hash(name, age); } } * HashMap存储自定义类型键值 * Map集合保证key是唯一的方法:作为key的元素,必须重写hashCode方法和equals方法 * * 下面案例是演示键为Person类型,需要在Person类中重写hashCode方法和equals方法。 * 值为String类型,不需重写。(只要求key唯一) public class Demo6_map { public static void main(String[] args) { show01(); } /** * HashMap存储自定义类型键值: * key:Person类型,Person类需要重写hashCode方法和equals方法,以保证key唯一。 * value:String类型,value可以重复 */ private static void show01(){ //创建HashMap集合(键为自定义Person类型,值为String) HashMap<Demo6_Person,String > map = new HashMap<>(); //往集合中添加元素 map.put(new Demo6_Person("彩鳞",18),"美杜莎"); map.put(new Demo6_Person("熏儿",19),"古族"); map.put(new Demo6_Person("云韵",20),"花宗"); map.put(new Demo6_Person("小医仙",18),"厄难毒体"); map.put(new Demo6_Person("彩鳞",18),"七彩吞天莽"); //使用EntrySet和增强for遍历map集合 //1.调用map中的EntrySet方法获取map中的Entry对象存于Set集合 Set<Map.Entry<Demo6_Person,String>>set=map.entrySet(); //2.遍历Set集合中Entry对象 for (Map.Entry<Demo6_Person, String> entry : set) { //3.Entry对象中的getKey和getValue方法获取Entry对象中的键值 Demo6_Person key = entry.getKey(); String value = entry.getValue(); System.out.println(key+":"+value); } } }
12.6.Map实现类_LinkedHashMap特点
- java.util.LinkedHashMap<k,v> extends HashMap<K,V>
- Map接口的哈希表和链表列表实现,具有可预知的的迭代顺序(有序),key唯一不重复。
- 底层结构:哈希表+链表(记录元素的顺序);
public class Demo7_LinkedHashMap { public static void main(String[] args) { HashMap<String, String> map = new HashMap<>(); map.put("a","a"); map.put("b","b"); map.put("c","c"); map.put("a","d"); System.out.println(map);//{a=d, b=b, c=c}key不允许重复,且无序。 LinkedHashMap<String, String> link = new LinkedHashMap<>(); link.put("a","a"); link.put("b","b"); link.put("c","c"); link.put("a","d");//{a=d, b=b, c=c}key不重复,有序 } }
12.7.HashMap与Hashtable区别
* 1.java.util.Hashtable<K,V>集合 implements Map<K,V>
* 2.HashMap与Hashtable的区别:
- Hashtable:底层也是一个哈希表,是一个线程安全(单线程)的集合,因此速度慢。
- HashMap: 底层是一个哈希表(数组+链表/红黑树),是一个线程不安全(多线程)的集合,因此速度快。
- HashMap集合(包括之前学的所有集合):都可以存储null键,null值
- hashtable集合,不能存储null键,null值
- Hashtable和vector集合一样,在jdk1.2版本之后被更先进集合(HashMap,ArrayList)取代
- Hashtable的子类Properties依然在使用,这个集合是一个唯一和IO流结合的集合。
public class Demo8_Hashtable { public static void main(String[] args) { HashMap<String, String> map = new HashMap<>(); map.put(null,"a"); map.put("b",null); map.put(null,null); Hashtable<String , String> table = new Hashtable<>(); table.put(null,"a");//NullPointerException空指针异常 table.put("b",null);//NullPointerException table.put(null,null);//NullPointerException //Hashtable集合中的键与值都不允许出现null } }
12.8.练习:字符串中每一个字符出现的次数
* 练习:计算一个字符串中每一个字符出现的次数 * 思路: * 1:使用Scanner获取用户输入的一个字符串 * 2:下面使用HashMap<Character,Integer>集合以键值对记录每个字符及对应的数量 * 3:首先需要遍历字符串,获取每一个字符,由两种方式: * i.String类的toCharArray方法,把字符串转换为数组,遍历数组即可。 * ii.String类的length方法加上charAt(索引)来获取每一个字符。 * 4:使用Map集合中方法判断获取到的字符串(key)是否存储在Map集合中 * i.使用Map集合中containsKey(获取的字符串)方法,返回布尔值 * true:字符存在 * 则通过字符(key),获取value(统计个数), * 把value++, * 把新的value存储到Map集合 * false:字符不存在 * 则把字符作为key,把1作为value存储到Map集合 * ii.或也可以使用Map集合中get(key)方法 * 返回null,表示key不存在,把对应键值对加入集合 * 返回不是null,则找到key对应的value自增后再存入集合。 public class Demo9_lianxi { public static void main(String[] args) { //1.使用Scanner获取用户输入的字符串 Scanner sc = new Scanner(System.in); System.out.println("请输入一个字符串"); String str = sc.next(); //2.创建Map集合,key是字符串的字符,value是字符个数 HashMap<Character, Integer> map = new HashMap<>(); //3.遍历字符串,获取每一个字符 for (char c:str.toCharArray()){ //4.使用获取到的字符,去Map集合判断key是否存在 if (map.containsKey(c)){ //key存在 Integer value = map.get(c); value++; map.put(c,value);//覆盖之前的键值对 }else{ //key不存在 map.put(c,1); } } /*for (Character key : map.keySet()) { Integer value = map.get(key); System.out.println(key+":"+value); }*/ System.out.println(map); /*输入asdfgasdfghj * 输出{a=2, s=2, d=2, f=2, g=2, h=1, j=1} * */ } }
package demo21;
import java.util.Collection;
import java.util.HashMap;
import java.util.Set;
/**
* Map
* HashMap/Hashtable/ConcurrentHashMap
* TreeMap
* LinkedHashMap
* 以上集合都适合下面操作
*/
public class HashMapMain {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
map.put("k1","你");
map.put("k2","好");
map.put("k3","啊");
map.put("k4","你");
String v = map.get("k1");
System.out.println(v);
System.out.println("======================");
Set<String> set = map.keySet();
for (String s:set) {
System.out.println(s+"->"+map.get(s));
}
System.out.println("======================");
Collection<String> values = map.values();
for (String s:values) {
System.out.print(s+" ");
}
}
}