7、Map接口
Collection、Set、List接口都属于单值的操作,而Map中的每个元素都使用key——>value的形式存储在集合中。
Map集合:该集合存储键值对。一对一对往里存。而且要保证键的唯一性。
Map的三个常用实现类
|--Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。jdk1.0.效率低。
|--HashMap:底层是哈希表数据结构,允许使用 null 值和 null 键,该集合是不同步的。将hashtable替代,jdk1.2.效率高。
|--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。
HashMap示例:
/**
Map集合:该集合存储键值对。一对一对往里存。而且要保证键的唯一性。
1,添加。
V | put(K key, V value)
void | putAll(Map<? extends K,? extends V> m)
2,删除。
void | clear()
V | remove(Object key)
3,判断。
boolean | containsValue(Object value)
boolean | containsKey(Object key)
boolean | isEmpty()
4,获取。
V | get(Object key)
int | size()
Collection<V> | values()
Set<Map.Entry<K,V>> | entrySet()
Set<K> | keySet()
Map的三个常用实现类
|--Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。jdk1.0.效率低。
|--HashMap:底层是哈希表数据结构,允许使用 null 值和 null 键,该集合是不同步的。将hashtable替代,jdk1.2.效率高。
|--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。
和Set很像。
其实大家,Set底层就是使用了Map集合。
*/
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class MapDemo {
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
// 添加 会返回被覆盖的值,
// 相同的键,后添加的值将会覆盖原有的值
// 键和值都可存入null
map.put("01","lisi1");
System.out.println(map.put("02","lisi2")); // null
System.out.println(map.put("02","lisi002")); // lisi2
map.put("03","lisi1");
map.put("04","lisi4");
map.put(null,null); // 键和值都可存入null
System.out.println(map); // {01=lisi1, 02=lisi002, 03=lisi3, 04=lisi4}
//删除
// System.out.println("remove:"+map.remove("01")); // 删除会返回删除的值
// map.clear(); // 清空
//判断
System.out.println(map.containsKey("010")); // true 是否包含这个key
System.out.println(map.containsValue("lisi1")); //true 是否包含这个值(一个或多个)
System.out.println(map.isEmpty()); // 该集合是否为空
// 获取
System.out.println(map.get("01")); // lisi1 获取值
System.out.println(map.size()); // 获取集合大小
Collection<String> values = map.values(); // 获取所有的值
System.out.println(values); // [lisi1, lisi002, lisi1, lisi4]
}
}
entrySet 方法图例
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/*
map集合的两种取出方式:
1,Set<k> keySet:将map中所有的键存入到Set集合。因为set具备迭代器。
所有可以迭代方式取出所有的键,在根据get方法。获取每一个键对应的值。
Map集合的取出原理:将map集合转成set集合。在通过迭代器取出。
2,Set<Map.Entry<k,v>> entrySet:将map集合中的映射关系存入到了set集合中,
而这个关系的数据类型就是:Map.Entry
Entry其实就是Map中的一个static内部接口。
为什么要定义在内部呢?
因为只有有了Map集合,有了键值对,才会有键值的映射关系。
关系属于Map集合中的一个内部事物。
而且该事物在直接访问Map集合中的元素。
*/
public class MapDemo2 {
public static void main(String[] args) {
// KeySet_Method();
Entry_Method();
}
public static void Entry_Method(){
Map<String,String> map = new HashMap<String,String>();
map.put("02","lisi02");
map.put("03","lisi03");
map.put("01","lisi01");
map.put("05","lisi05");
// entrySet() 将map 集合的映射关系存到set集合中 Map.Entry<String,String> 相当于一个映射关系类型
Set<Map.Entry<String,String>> entrySet = map.entrySet();
for (Iterator<Map.Entry<String, String>> it = entrySet.iterator(); it.hasNext();){
Map.Entry<String,String> entry = it.next(); //获取一个映射关系
// 通过映射关系中提供的getKey() 和 getValue() 获取键和值
System.out.println(entry.getKey()+":"+entry.getValue());
}
}
public static void KeySet_Method() {
Map<String,String> map = new HashMap<String,String>();
map.put("02","lisi02");
map.put("03","lisi03");
map.put("01","lisi01");
map.put("05","lisi05");
// keySet:获取所有的键,返回Set
Set<String> keys = map.keySet();
for(Iterator it = keys.iterator(); it.hasNext();){
//get(key) 获取每个键的值
System.out.println(map.get(it.next()));
}
}
}
hashMap 练习
每一个学生都有对应的归属地。
学生Student,地址String。
学生属性:姓名,年龄。
注意:姓名和年龄相同的视为同一个学生。保证学生的唯一性。
import java.util.*;
/*
每一个学生都有对应的归属地。
学生Student,地址String。
学生属性:姓名,年龄。
注意:姓名和年龄相同的视为同一个学生。保证学生的唯一性。
1,描述学生。
2,定义map容器。将学生作为键,地址作为值。存入。
3,获取map集合中的元素。
*/
public class MapTest {
public static void main(String[] args) {
Map<Student,String> map = new HashMap<Student,String>();
map.put(new Student("lisi1",20),"beijing");
map.put(new Student("lisi2",22),"beijing");
map.put(new Student("lisi3",24),"nanjing");
map.put(new Student("lisi4",20),"shanghai");
//map.put(new Student("lisi4",20),"shanghai"); // 不会被添加
// 遍历map keySet
// for(Iterator<Student> it = map.keySet().iterator();it.hasNext();){
// Student s = it.next();
// String value = map.get(s);
// System.out.println(s.toString()+":"+value);
// }
// EntrySet 遍历
Set<Map.Entry<Student,String>> emptySet = map.entrySet();
for (Iterator<Map.Entry<Student,String>> it = emptySet.iterator();it.hasNext();){
Map.Entry<Student,String> entry = it.next();
System.out.println(entry.getKey()+":"+entry.getValue());
}
}
}
class Student{
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
// 姓名和年龄相同的视为同一个学生。保证学生的唯一性,必须重写hashCode() 和 equals()
public int hashCode(){
return this.name.hashCode()+age*11;
}
public boolean equals(Object obj){
if(!(obj instanceof Student)){
throw new ClassCastException("类型不匹配");
}
Student s = (Student)obj;
return this.name.equals(s.name) && this.age == s.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 +
'}';
}
}
TreeMap练习(自定义比较)
按照年龄进行排序
package 集合.Map;
import java.util.*;
/*
每一个学生都有对应的归属地。
学生Student,地址String。
学生属性:姓名,年龄。
注意:姓名和年龄相同的视为同一个学生。保证学生的唯一性。
按照年龄进行排序
1. 让元素本身具备比较性
实现Comparable接口,重写compareTo()
2. 自定义比较器
定义一个类,实现Comparator接口,重写compare()
*/
public class TreeMapTest{
public static void main(String[] args) {
TreeMap<Student, String> tmap = new TreeMap<Student, String>(new NameComparator());
tmap.put(new Student("lisi1",20),"beijing");
tmap.put(new Student("lisi2",22),"beijing");
tmap.put(new Student("lisi3",24),"nanjing");
tmap.put(new Student("lisi3",22),"nanjing");
tmap.put(new Student("lisi4",20),"shanghai");
Set<Map.Entry<Student,String>> entrySet = tmap.entrySet();
for (Iterator<Map.Entry<Student, String>> it = entrySet.iterator(); it.hasNext();){
Map.Entry<Student,String> entry = it.next(); //获取一个映射关系
// 通过映射关系中提供的getKey() 和 getValue() 获取键和值
System.out.println(entry.getKey()+":"+entry.getValue());
}
}
}
//通过姓名进行排序
class NameComparator implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
int num = o1.getName().compareTo(o2.getName());
if(num == 0){
return new Integer(o1.getAge()).compareTo(new Integer(o2.getAge()));
}
return num;
}
}
class Student implements Comparable<Student>{
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
// 姓名和年龄相同的视为同一个学生。保证学生的唯一性,必须重写hashCode() 和 equals()
public int hashCode(){
return this.name.hashCode()+age*11;
}
public boolean equals(Object obj){
if(!(obj instanceof Student)){
throw new ClassCastException("类型不匹配");
}
Student s = (Student)obj;
return this.name.equals(s.name) && this.age == s.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 +
'}';
}
@Override
public int compareTo(Student s) {
int num = new Integer(this.age).compareTo(new Integer(s.age));
if(num == 0){
return this.name.compareTo(s.name);
}
return num;
}
}
练习:
"sdfgzxcvasdfxcvdf"获取该字符串中的字母出现的次数。希望打印结果:a(1)c(2).....
/*
练习:
"sdfgzxcvasdfxcvdf"获取该字符串中的字母出现的次数。
希望打印结果:a(1)c(2).....
通过结果发现,每一个字母都有对应的次数。
说明字母和次数之间都有映射关系。
注意了,当发现有映射关系时,可以选择map集合。
因为map集合中存放就是映射关系。
什么使用map集合呢?
当数据之间存在这映射关系时,就要先想map集合。
思路:
1,将字符串转换成字符数组。因为要对每一个字母进行操作。
2,定义一个map集合,因为打印结果的字母有顺序,所以使用treemap集合。
3,遍历字符数组。
将每一个字母作为键去查map集合。
如果返回null,将该字母和1存入到map集合中。
如果返回不是null,说明该字母在map集合已经存在并有对应次数。
那么就获取该次数并进行自增。,然后将该字母和自增后的次数存入到map集合中。覆盖调用原理键所对应的值。
4,将map集合中的数据变成指定的字符串形式返回。
*/
public class TreeMapTest2 {
public static void main(String[] args) {
String s = "abcabdef%cb--cdedd++ff";
System.out.println(WordCount(s));
}
public static String WordCount(String s){
Map<Character,Integer> map = new TreeMap<Character,Integer>();
//1. 将字符串转换成字符数组
char[] ch = s.toCharArray();
//2.遍历字符串数组,判断map 中是否存在,
for (int i = 0; i < ch.length; i++) {
// 只统计字母
if(!(ch[i] > 'a' && ch[i] < 'z' || ch[i] > 'A' && ch[i] < 'Z'))
continue;
Integer v = map.get(ch[i]);
if (v == null){
map.put(ch[i],1);
}else {
v++;
map.put(ch[i],v); // 会覆盖掉键相同的
}
}
//3.输出a(1)c(2).....
StringBuilder builder = new StringBuilder();
Set<Map.Entry<Character,Integer>> entrySet = map.entrySet();
for(Iterator<Map.Entry<Character,Integer>> it = entrySet.iterator();it.hasNext();){
Map.Entry<Character,Integer> entry= it.next();
builder.append(entry.getKey()+"("+entry.getValue()+")");
}
return builder.toString();
}
}
map扩展
/*
map扩展知识。
map集合被使用是因为具备映射关系。
"jiuyeban" "01" "wangwu";
"jiuyeban" "02" "zhaoliu";
一个学校有多个教室。每一个教室都有名称。
*/
import java.util.*;
public class MapDemo3 {
public static void main(String[] args) {
// 创建一个学校map
Map<String, HashMap<String,String>> school = new HashMap<String, HashMap<String,String>>();
//创建两个班级map
HashMap<String,String> jichuban = new HashMap<String,String>();
HashMap<String,String> jiuyeban = new HashMap<String,String>();
school.put("就业班",jiuyeban);
school.put("基础班",jichuban);
jichuban.put("01","张三");
jichuban.put("02","李四");
jiuyeban.put("01","小明");
jiuyeban.put("02","小强");
// 获取每一个学生
Set<Map.Entry<String, HashMap<String,String>>> entrySet = school.entrySet();
for(Iterator<Map.Entry<String, HashMap<String,String>>> it = entrySet.iterator();it.hasNext();){
Map.Entry<String, HashMap<String,String>> entry = it.next();
// System.out.println(entry.getKey()+":"+entry.getValue());
// 遍历每个班级 通过keySet()
for (Iterator<String> it1 = entry.getValue().keySet().iterator();it1.hasNext();){
String key = it1.next();
String value = entry.getValue().get(key);
System.out.println(key+":"+value);
}
}
}
}
package 集合.Map;
/*
map扩展知识。
map集合被使用是因为具备映射关系。
"yureban" Student("01" "zhangsan");
"yureban" Student("02" "lisi");
一个学校有多个教室。每一个教室都有名称。
*/
import java.util.*;
public class MapDemo4 {
public static void main(String[] args) {
// 创建一个学校map
Map<String, List<Student>> school = new HashMap<String, List<Student>>();
//创建两个班级List
List<Student> jichuban = new ArrayList<Student>();
List<Student> jiuyeban = new ArrayList<Student>();
school.put("就业班",jiuyeban);
school.put("基础班",jichuban);
jichuban.add(new Student("01","张三"));
jichuban.add(new Student("02","李四"));
jiuyeban.add(new Student("01","小明"));
jiuyeban.add(new Student("02","小强"));
// 获取每一个学生
Set<Map.Entry<String, List<Student>>> entrySet = school.entrySet();
for(Iterator<Map.Entry<String, List<Student>>> it = entrySet.iterator();it.hasNext();){
Map.Entry<String, List<Student>> entry = it.next();
List<Student> list = entry.getValue(); // 获取教师列表
for(Iterator<Student> it1 = list.iterator();it1.hasNext();){
System.out.println(it1.next()); // 获取每个学生
}
}
}
}
class Student{
private String id;
private String name;
public Student(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
}