Java-31 Map集合
- Map集合:(由哈希表和链表实现)
- HashMap:
- 底层是一个哈希表,是一个线程不安全的集合,是多线程集合,速度快
- jdk1.8之前:数组+单向链表
- jdk1.8之后:数组+单项链表/红黑树(链表长度超过8):提高查询速度
- 可以存储null值和null键
- 是一个无序集合,存储元素和取出元素可能不一致
- 底层是一个哈希表,是一个线程不安全的集合,是多线程集合,速度快
- HashTable:
- 底层是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢
- 不可以存储null值和null键
- Hashtable和Vector集合一样,在jdk1.2版本之后被更先迸的集合(HashMap, ArrayL ist)取代了,但是Hashtable的子类Properties依然活趺在万史舞台
- Properties集合是一个唯一和I0流相结合的集合
- LinkedHashMap:
- 底层是哈希表+链表,是一个线程不安全的集合,是多线程集合,速度快
- 集合是一个有序集合,存储元素和取出元素顺序一致
- TreeMap:
- 底层是基于红黑树的Map接口的实现类,是一个线程不安全的集合,是多线程集合,速度快
-
键是红黑树结构,可以保证键的排序和唯一性
- HashMap:
- Map集合的特点:
1.Map集合是一个双列集合,一个元素包含两个值(一个key, 一个value)
2. Map集合中的元素, key和value的数据类型可以相同,也可以不同
3.Map集合中的元素,key是不允许重复的,volue是可以重复的
4. Map集合中的元素, key和value是一一对应
- Map接口和Collection接口的不同:
1、它们两个不存在继承关系,都是属于java.util包下面的平级关系
2、Map集合存储的元素都是成对出现的,Map元素的键是唯一的,值是可以重复。把这样的元素理解为:夫妻对
3、Collection集合存储的元素都是单独出现的,Collection接口下面的Set是元素唯一的。List集合中元素是可以重复的。这样的单独出现的元素:光棍
- Map集合的功能:(以HashMap为例)
1、添加功能:
V put(K key,V value)将指定的值与该映射中的指定键相关联(可选操作)。
2、删除功能:
V remove(Object key)如果存在(从可选的操作),从该地图中删除一个键的映射
void clear()从该地图中删除所有的映射(可选操作)
3、判断功能:
boolean containsKey(Object key)
boolean containsValue(Object value)
boolean isEmpty()
4、长度功能:
int size()返回此地图中键值映射的数量
public class HashMapDemo1 { public static void main(String[] args) { HashMap<String, Integer> map = new HashMap<>(); //添加功能:V put(K key,V value)将指定的值与该映射中的指定键相关联(可选操作)。 System.out.println(map.put("张三", 18));//null System.out.println(map.put("张三", 19));//18 两次插入同一个key的映射的时候,返回的是该key上一个映射中对应的值 map.put("李四",18); map.put("王五",18); map.put("赵六",18); map.put("田七",18); System.out.println(map);//{李四=18, 张三=19} 说明map重写了tostring方法 System.out.println("==========================="); //删除功能: //V remove(Object key)如果存在(从可选的操作),从该地图中删除一个键的映射 System.out.println(map.remove("张三"));//19 根据key移除,返回的是映射中对应值 System.out.println(map);//{李四=18, 王五=18, 赵六=18, 田七=18} System.out.println("=========================="); //void clear()从该地图中删除所有的映射(可选操作) // map.clear(); // System.out.println(map);//{} //判断功能: //boolean isEmpty() System.out.println(map.isEmpty());//false //boolean containsKey(Object key) System.out.println(map.containsKey("张三"));//false //boolean containsValue(Object value) System.out.println(map.containsValue(18));//false //长度功能: //int size()返回此地图中键值映射的数量 System.out.println(map.size());//4 System.out.println(map);//{李四=18, 王五=18, 赵六=18, 田七=18} } }
5、获取功能:(多用于集合遍历)
Set<Map.Entry<K,V>> entrySet()返回此Map中包含的映射的Set视图。
V get(Object key)返回到指定键所映射的值,或null如果此映射包含该键的映射。
Set<K> keySet()返回此地图中包含的键的Set视图。
Collection<V> values()返回此地图中包含的值的Collection视图。
6、Map集合两种遍历方法
1、键找值遍历

2、键值对对像遍历

import java.util.*; /* Map集合的获取功能: V get(Object key)返回到指定键所映射的值,或null如果此映射包含该键的映射。 Set<K> keySet()返回此地图中包含的键的Set视图。 Collection<V> values()返回此地图中包含的值的Collection视图。 Map集合两种遍历方法 1、键找值遍历 2、键值对对像遍历 */ public class HashMapDemo2 { public static void main(String[] args) { //新建集合对象 HashMap<String, Integer> map = new HashMap<>(); map.put("张三",18); map.put("李四",18); map.put("王五",18); map.put("赵六",18); map.put("田七",18); map.put("古力娜扎",18); map.put("迪丽热巴",18); //Map集合的获取功能: //V get(Object key)返回到指定键所映射的值,或null如果此映射包含该键的映射。 //Set<K> keySet()返回此地图中包含的键的Set视图。 //Collection<V> values()返回此地图中包含的值的Collection视图。 Collection<Integer> values = map.values(); System.out.println(values);//[18, 18, 18, 18, 18, 18, 18] //集合遍历 //方式一 键找值遍历 //Set<K> keySet()返回此地图中包含的键的Set视图。 Set<String> strings = map.keySet(); //迭代器遍历 Iterator<String> iterator = strings.iterator(); while(iterator.hasNext()){ String key = iterator.next(); //V get(Object key)返回到指定键所映射的值,或null如果此映射包含该键的映射 Integer value = map.get(key); System.out.println(key+"---"+value); } System.out.println("======================"); //增强for循环 for (String key : strings) { Integer value = map.get(key); System.out.println(key+"---"+value); } System.out.println("======================"); //方式二 //键值对对象遍历 //Set<Map.Entry<K,V>> entrySet()返回此地图中包含的映射的Set视图。 //Map.Entry接口中有两个方法可以获取键和值 //K getKey()返回与此条目相对应的键。 //V getValue()返回与此条目相对应的值。 Set<Map.Entry<String, Integer>> entries = map.entrySet(); //增强for循环遍历 for (Map.Entry<String, Integer> entry : entries) { String key = entry.getKey(); Integer value = entry.getValue(); System.out.println(key+"---"+value); } System.out.println("============================="); //迭代器遍历 Iterator<Map.Entry<String, Integer>> iterator1 = entries.iterator(); while (iterator1.hasNext()){ Map.Entry<String, Integer> next = iterator1.next(); String key = next.getKey(); Integer value = next.getValue(); System.out.println(key+"---"+value); } } }
HashMap案例注意事项:
HashMap<String,Student>:值可以相同
HashMap<Student,String>:键值是学生类对象,注意重写equals和hashcode方法,确保键值元素不同
HashTable:
import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import java.util.Set; /* HashMap和Hashtable的区别 1、相同点:它们存储的元素类型都是K-V格式的 2、不同点: 1)Hashtable是线程安全的HashMap不是线程安全的 2)Hashtable的key的值和value的值都不允许为null,而HashMap */ public class HashMapAndHashtable { public static void main(String[] args) { HashMap<String, String> map1 = new HashMap<String, String>(); Hashtable<String, String> map2 = new Hashtable<String, String>(); map1.put(null,null); // map2.put("hello",null); Set<Map.Entry<String, String>> entries = map1.entrySet(); for (Map.Entry<String, String> entry : entries) { String key = entry.getKey(); String value = entry.getValue(); System.out.println(key+"---"+value); } // Set<Map.Entry<String, String>> entries1 = map2.entrySet(); // for (Map.Entry<String, String> entry : entries1) { // String key = entry.getKey(); // String value = entry.getValue(); // System.out.println(key+"---"+value); // } } }
LinkedHashMap:
import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; /* LinkedHashMapDemo:是实现了Map接口,底层是依赖于哈希表和链表的,具有可预知的遍历顺序 哈希表保证唯一性,保证的是Key的唯一性 链表保证有序,保证的是键的有序(存储和取出顺序一致) */ //注意,类的名字不要和API中提供的类名相同 public class LinkedHashMapDemo { public static void main(String[] args) { LinkedHashMap<String, String> linkedMap = new LinkedHashMap<String, String>(); //添加元素到集合中 linkedMap.put("4321", "world"); linkedMap.put("1234", "hello"); linkedMap.put("3456", "bigdata"); linkedMap.put("1234", "hadoop"); linkedMap.put("3456", "spark"); //遍历 Set<Map.Entry<String, String>> entries = linkedMap.entrySet(); for (Map.Entry<String, String> entry : entries) { String key = entry.getKey(); String value = entry.getValue(); System.out.println(key + "---" + value); } } }

TreeMap类:
键是红黑树结构,可以保证键的排序和唯一性
TreeMap案例
HashMap<String,String>
import java.util.Map; import java.util.Set; import java.util.TreeMap; /* TreeMap :底层是基于红黑树的Map接口的实现类 HashMap<String,String> */ public class TreeMapDemo1 { public static void main(String[] args) { //创建集合对象 TreeMap<String, String> map = new TreeMap<String, String>(); //创建元素并添加到集合中 map.put("hello", "你好"); map.put("java", "面向对象的编程语言"); map.put("mysql", "关系型结构化数据库"); map.put("springBoot", "spring框架"); map.put("springBoot", "spring"); //遍历 Set<Map.Entry<String, String>> entries = map.entrySet(); for (Map.Entry<String, String> entry : entries) { String key = entry.getKey(); String value = entry.getValue(); System.out.println(key + "---" + value); } } }
HashMap<Student,String>
import java.util.Comparator; import java.util.Map; import java.util.Set; import java.util.TreeMap; /* HashMap<Student,String> 键:Student 值:String */ public class TreeMapDemo2 { public static void main(String[] args) { //创建集合对象 TreeMap<Student, String> map = new TreeMap<>(new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { //年龄 int i = o2.getAge() - o1.getAge(); //年龄一样,姓名不一定一样 int i2 = i == 0 ? o1.getName().compareTo(o2.getName()) : i; return i2; } }); //创建学生对象 Student s1 = new Student("张三", 18); Student s2 = new Student("李四", 18); Student s3 = new Student("王五", 18); Student s4 = new Student("赵六", 18); Student s5 = new Student("赵六", 18); //将元素添加到集合中 map.put(s1,"班长"); map.put(s2,"团委"); map.put(s3,"学委"); map.put(s4,"体育委员"); map.put(s5,"心理委员"); //遍历 Set<Map.Entry<Student, String>> entries = map.entrySet(); for (Map.Entry<Student, String> entry : entries) { Student key = entry.getKey(); String value = entry.getValue(); System.out.println(key+"---"+value); } } }
public class Student { private String name; private int age; public Student() { } public Student(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 "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
小练习案例:
键盘录入字符串。
获取字符串中每一个字母出现的次数要求结果

import java.util.Map; import java.util.Scanner; import java.util.Set; import java.util.TreeMap; /* 键盘录入字符串。 获取字符串中每一个字母出现的次数要求结果:a(5)b(4)c(3)d(2)e(1) 分析: 1、键盘录入一个字符串 2、创建一个集合对象TreeMap key: Character value: Integer 3、将字符串转成字符串数组 4、遍历字符数组获取到每一个字符 5、拿到字符去集合的键找,看看有没有这个键 如果没有对应的键,就把这个字符当作key,value值为1进行存储 如果有对应的键,把value值+1,重新存储到集合中 6、定义一个StringBuilder作为拼接 7、遍历集合,得到键和值,按照指定的输出个进行拼接a(5)b(4)c(3)d(2)e(1) 8、把StringBuilder转成字符串输出 */ public class TreeMapText { public static void main(String[] args) { //创建键盘录入对象 Scanner sc = new Scanner(System.in); System.out.println("请输入一个纯英文的字符串:"); String s = sc.next(); //创建一个集合对象 TreeMap<Character, Integer> map = new TreeMap<Character, Integer>(); //将字符串转成字符串数组 char[] charArray = s.toCharArray(); //遍历字符数组获取到每一个字符 for (char c : charArray) { //拿到字符去集合的键找,看看有没有这个键 // boolean b = map.containsKey(c); Integer i = map.get(c); //判断这个b的值,如果是true,说明集合中已经存在该key //如果说返回的值是false,说明集合还没有该key存在 if (i == null) { map.put(c, 1); } else { i++; map.put(c, i); } } //定义一个StringBuffer作为拼接 // StringBuilder sb = new StringBuilder(); StringBuffer sb = new StringBuffer(); //遍历集合,得到键和值,按照指定的输出个进行拼接 Set<Map.Entry<Character, Integer>> entries = map.entrySet(); for (Map.Entry<Character, Integer> entry : entries) { Character key = entry.getKey(); Integer value = entry.getValue(); sb.append(key).append("(").append(value).append(")"); } //将StringBuffer转成字符串输出 String s1 = sb.toString(); System.out.println("计算结果为:" + s1); } }


浙公网安备 33010602011771号