Map集合:存在键值关系的集合,称为Map集合

之前谈到的Set,Collection集合他是一个单列的集合,你可以根据某一个对象的属性来找出某个想要的元素,那么今天所说的Map集合他是一个双列集合,有键和值(Map<K,V>    K是映射键的类型,V是映射值的类型)。Map集合的数据结果都只和键有关,好,今天看看他的三个已知实现类:HashMap,LinkendHashMap和TreeMap。

HashMap:HashMap他是基于哈希表的Map接口的实现。他提供所有可选dede 映射操作,并且允许使用null值de和null键。(除了不同步和允许使用null值之外,HashMap类与Hashtable大致相同,此类不保证映射的顺序,就是说打印出来的结果不一定是按写的顺序排列的。)

当创建HashMap集合之后,用put方法添加元素时,第一次添加的键和值之后,返回一个数据类型,打印这个数据类型时,输出的是一个null,系统默认这对键值对是第一次赋值,当键值不变时,把值换成另外一个值,这是在打印这个数据类型时,仍然是打印出第一次赋值的值,但是最后打印这个集合时,输出的是第二次赋值的键值对,这里存在一个键相同值覆盖的问题(因为一个键只能映射一个值)。好,下来我们举例说明下,

先创建一个HashMap集合;

Map<String,String>   hashMap=new HashMap<String,String>();
String put=hashMap.put("赵雷",“成都”);
System.out.println(put);        //此时输出的值是null;
String put2=hashMap.put("赵雷","吉姆餐厅");   //此时是键不变,值换掉了
System.out.println(put2);    //此时输出的值是“成都”,这个是根据键找值,当键相同时,返回的是上一次的值
hashMap.put("赵雷","南方姑娘");
hashMap.put("宋冬野","安河桥");
hashMap.put("朴树","平凡之路");
System.println(hashMap);

控制台输出:

   null

  成都

  {宋冬野--安河桥,赵雷--南方姑娘,赵雷--吉姆餐厅,朴树--平凡之路  }元素的排列顺序是无序的,(输出的集合里,吉姆餐厅替换掉了成都,是因为一个键只能映射一个值,即键相同值覆盖)

当然,每一个集合都有一些功能,HashMap也不例外:

void  clear():清除所有映射关系,即所有的键值对;

public V remove():集合中移除一对键值对

判断功能:

boolean  containsKey(Object  key):判断是否存在某个键

boolean  containsValue(Object value):判断是否存在某个值

boolean isEmpty:判断是否为空。

好,以上我们来举例说明:

Map<Integer,String>  hashMap=new  HashMap<Integer,String>();     //泛型里边只能是引用数据类型
hashMap.put(1,"赵雷");
hashMap.put(2,"朴树");
hashMap.put(3,"张卫健");
hashMap.put(4,"黄海波");
hashMap.clear();      //调用clear功能将清除所有的键值对
hashMap.remove(1);
  System.out.println(hashMap);//只需要输入键值,便会删除掉这个键值对。

键找值:

Map<String,String> hashMap=new HashMap<String,String>();
hashMap.put("路遥","平凡的世界");
hashMap.put("刘同","你的孤独,虽败犹荣");
hashMap.put("曹文轩","草房子");
hashMap.put("莫言","四十一炮");
String str=hashMap.get("刘同");
System.out.println(str);      //此时,”刘同“对应的值应该是“你的孤独,虽败犹荣”

获取所有的值:

Collection<String> value=hashMap.values();
for(String str2:value){
            System.out.println(str2);
}

值找键(获取所有的键):

Set<String>   key=hashMap.keySet();
for(String str3:key){
       System.out.println(str3);
}
//再加上一句获得集合元素长度
System.out.println(hashMap.size());

下来再来看个例子:

public class HashMapDemo{
      public static void main(String[] args){
  Map<String,String> hashMap= new  HashMap<String,String>();
 hashMap.put("朴树","那些花儿");
 hashMap.put("赵雷","南方姑娘");        //HashMap允许插入null值null键
 hashMap.put("张卫健","疼爱");
 hashMap.put("胡夏","那些年");

现在来遍历集合:(方式一)

Set<String>  key=hashMap.keySet();
for(String str: key){
String  value=str.get(key);
System.out.println(key+"----"+value);
}

遍历集合:(方式二:键值对 对象)

Set<Map.Entry<String,String>>  entry=hashMap.entrySet();
     for(Map.Entry<String,String>  entries:entry){
           String key=  entries.getKey();
           String value=entries.getValue();
}
System.out.println(key+"---"+value);
}
}

问题一:下来我们看一下给一个自定义类,该如何去遍历集合呢?(键是String  值是Student类)

写一个标准学生类

public class Student{
  private  String name;
 private int age;
public Student(){}
public Student(Stringf name,int age){
       this.name=name;
       this.age=age;
}
public String getName(){
   return name;
}
public void setNme(String name){
  this.name=name;
}
public int getAge(){
     rerurn   age;
   }
public  void setAge(int age){
   this.age=age;
}
@Override
 public String toString(){
  return  "Student [ name="+name+",  age="+age+"]"
}
}
public class HashMapDemo{
         public static void main(String[] args){
Map<String,Student> hashMap=new HashMap<String,Student>();
hashMap.put("a0001",new Student(陈小帅",21));
hashMap.put("a0001",new Student(吴大能",23));
hashMap.put("a0001",new Student(滑小稽",24));
hashMap.put("a0001",new Student(熊本熊",22));
Set<String>  string=hashMap.keySet();       //方式一:keySet,get方法遍历
  for(String str:string){
             Student student= hashMap.get(str);
         System.out.println(str+"---"+student.getName()+"---"+student.getAge());
}

方式二:entrySet来遍历

Set<Map.Entry<String,Student>>entry=hashMap.entrySet<String,Student>();
   for(Map.Entry<String,Student>  entrys:entry){
         String key=entrys.getKey();
         String value=entrys.getValue();
   System.out.println(key+"---"+value,getName()+"---"+value.getAge());
}
}
}

问题二:接下来我们给同一个自定义类,(键是Student类 值是String类)该如何去遍历集合呢?

(此处同样使用问题一中的标准学生类)

public  class HashMapDemo2{
           public static void  mian(String[] args){
Map<Student,String>hashMap=new HashMap<Student,String>();
hashMap.put(new Student(陈小帅",21),"a0001");
hashMap.put(new Student(吴大能",23),"a0001");
hashMap.put(new Student(滑小稽",24),"a0001");
hashMap.put(new Student(熊本熊",22),"a0001");
Set<Student>  student=hashMap.keySet();       //方式一:  keySet,get
for(Student students:student){
                String value=hashMap.get(students);
System.out.println(students.getName()+"---"+students.getAge()+"---"+value);
}
方式二:  entrySet
Set<Map.Entry<Student,String>>  entry=hashMap.entrySet<Student,String>();
   for(Map.Entry<Student,String>  entrys:entry){
                 Student student=entrys.getKey();
                 String value=entrys.getValue();
    System.out.println(student.getName()+"---"+student.getAge()+"---"+value);
}
}
}

LinkedHashMap:

  Map的哈希表和链表的列表实现,具有可知的迭代顺序(即迭代顺序和赋值的顺序有关,正向或者逆向迭代)

LinkedHashMap的底层数据结构是哈希表和链表,元素有序且唯一,有序由链表保证,唯一由哈希表保证,线程数据不安全,执行效率高,Map集合的值只和键有关

好下来我们来看一个具体的例子:

LinkedHashMap<Integer,String> hashMap=new  LinkedHashMap<Integer,String>();
hashMap.put(2,"赵雷");
hashMap.put(1,"朴树");
hashMap.put(4,"张卫健");
hashMap.put(3,"高圆圆");
Set<Integer> keys=hashMap.keySet();
for(Integer key:keys){
             String value= hashMap.get(key);
     System.out.println(key+"---"+value);
}

TreeMap:

底层数据结构是二叉树,元素唯一且排序。排序分为自然排序和比较器排序。以下也是用两个具体的例子来说明一下

方式一:自然排序

先建一个标准教师类,

public class Teacher implements Comparable<Teacher>{
     private String name;
     private int age;
     
     public Teacher() {
         super();
     }
     public Teacher(String name, int age) {
         super();
         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 "Teacher [name=" + name + ", age=" + age + "]";
     }
     @Override
     public int compareTo(Teacher s) {
         int r=this.age-s.age;
         int r2=r==0? this.name.length()-s.name.length():r;       //加黑部分下边会有说明
         return r2;
     }
 }


public class TreeMapDemo {
     public static void main(String[] args) {
         TreeMap<Teacher, String> treeMap = new TreeMap<>();
         treeMap.put(new Teacher("陈老师",18),"t001");  //如果没有实现Comparable接口,没有重写CompareTo方法,此处会有空指针异常,所以必须实现Comparable接口,必须重写ComparaTo方法,根据返回值来决定排列顺序
         treeMap.put(new Teacher("张老师", 19), "t001");
         treeMap.put(new Teacher("王老师", 30), "t001");
         treeMap.put(new Teacher("李老师", 20), null);//可以插入null,treeMap.put(null,"t009"); 不允许插入null键
         Set<Map.Entry<Teacher, String>> entries = treeMap.entrySet();
         for(Map.Entry<Teacher, String> entry:entries){
             Teacher key = entry.getKey();
             String value = entry.getValue();
             System.out.println(key.getName()+"---"+key.getAge()+"---"+value);
         }
     }
 }

方式二:比较器排序

建立一个学生类

public class Student {
     private String name;
     private int age;
     public Student() {
         super();
     }
     public Student(String name, int age) {
         super();
         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 + "]";
     }
 }

测试学生类,遍历集合。

public class TreeMapDemo2 {
     public static void main(String[] args) {
         TreeMap<Student3, String> treeMap = new TreeMap<>(new Comparator<Student3>(){
             @Override
             public int compare(Student3 s1, Student3 s2) {
                 int r=s1.getName().length()-s2.getName().length();
                 int r2=r==0? s1.getAge()-s2.getAge():r;
                 return r2;
             }
         });
         treeMap.put(new Student3(" 陈小帅", 18),"c9527");
         treeMap.put(new Student3(" 滑小稽", 34),"a2221");
         treeMap.put(new Student3(" 大熊猫", 25),"b0001");
         treeMap.put(new Student3(" 张卫健", 28),"e8888");
         Set<Entry<Student3, String>> entrys=treeMap.entrySet();
         
         for(Entry<Student3, String> entry:entrys) {
             Student3 key = entry.getKey();
             String value = entry.getValue();
             System.out.println(key.getName()+"---"+key.getAge()+"---"+value);
         }
     }
 }

下来再来看一下集合的嵌套,很重要,但是我觉得也很难,暂时的难只是时间问题,男人没有解决不了的事情

基础班
            张三   20
             李四   22

就业班
            王五    21
            赵六    23

代码实现下:

public class HashMapDemo2 {
     public static void main(String[] args) {
         HashMap<String, Integer> hashMap = new HashMap<>();
         hashMap.put("张三", 20);
         hashMap.put("李四", 22);
         HashMap<String, Integer> hashMap2 = new HashMap<>();
         hashMap2.put("王五", 21);
         hashMap2.put("赵六", 23);
         HashMap<String, HashMap<String, Integer>> hashMap3 = new HashMap<>();
         hashMap3.put("基础班", hashMap);
         hashMap3.put("就业班", hashMap2);
         Set<String> keys = hashMap3.keySet();
         for (String key : keys) {
             System.out.println(key);
             HashMap<String, Integer> map = hashMap3.get(key);
             Set<String> keySet = map.keySet();
             for (String values : keySet) {
                 Integer value = map.get(values);
                 System.out.println("\t" + key + "-----" + value);
             }
             System.out.println();
         }
     }
 }

再开看一看如何统计一个字符串中每个字符出现的次数

public class MyMapDemo {
     public static void main(String[] args) {
              HashMap<Character, Integer> map = new HashMap<>();
         Scanner sc = new Scanner(System.in);
         System.out.println("请随便输入一段字符串");
         String line = sc.next();
         //我怎么来统计字符出现的次数呢?统计完之后,把键值关系的数据存到集合中
         for (int i = 0; i < line.length(); i++) {
             //获取单个字符
             char key = line.charAt(i);
             //abfefdadfefdaeaaaddd
             
             if (map.get(key) == null) {
                 map.put(key, 1);
             } else {
                 Integer value = map.get(key);
                 value++;
                 map.put(key, value);
             }
         }
         //  System.out.println(map);a(5) b(4) c(3) d(2) e(1)
         //遍历集合拼串
         StringBuffer sb = new StringBuffer();
         Set<Character> characters = map.keySet();
         for (Character ch : characters) {
             sb.append(ch).append("(").append(map.get(ch)).append(")");
         }
         String s = sb.toString();
         System.out.println("你要的结果" + s);
     }
 }


Map嵌套List集合:

public class MyMapDemo3 {
     public static void main(String[] args) {
        三国演义
               吕布
               周瑜
       笑傲江湖
                 令狐冲
                 林平之
       神雕侠侣
             郭靖
              杨过
         把上面这组数据存起来  HashMap 嵌套List
         ArrayList<String> sgyy = new ArrayList<>();
         sgyy.add("吕布");
         sgyy.add("周瑜");
         ArrayList<String> xajh = new ArrayList<>();
         xajh.add("令狐冲");
         xajh.add("林平之");
         ArrayList<String> sjxl = new ArrayList<>();
         sjxl.add("郭靖");
         sjxl.add("杨过");        HashMap<String, ArrayList<String>> hm = new HashMap<>();
         hm.put("笑傲江湖", xajh);
         hm.put("神雕侠侣", sjxl);
         hm.put("三国演义", sgyy);
         //遍历
         Set<Map.Entry<String, ArrayList<String>>> entries = hm.entrySet();
         for (Map.Entry<String, ArrayList<String>> en : entries) {
             String key = en.getKey();
             System.out.println(key);
             ArrayList<String> value = en.getValue();
             for (String k : value) {
                 System.out.println("\t"+k);
             }
             System.out.println();
         }
     }
 }


List集合嵌套Map集合

public class MyMapDemo4 {
     public static void main(String[] args) {
             周瑜-- - 小乔
             吕布-- - 貂蝉
              
             郭靖-- - 黄蓉
             杨过-- - 小龙女
         
             令狐冲-- - 任盈盈
             林平之-- - 岳灵珊
         Map<String, String> sgyy = new HashMap<>();
         sgyy.put("周瑜", "小乔");
         sgyy.put("吕布", "貂蝉");        Map<String, String> sdxl = new HashMap<>();
         sdxl.put("郭靖", "黄蓉");
         sdxl.put("杨过", "小龙女");        Map<String, String> xajh = new HashMap<>();
         sdxl.put("令狐冲", "任盈盈");
         sdxl.put("林平之", "岳灵珊");
         ArrayList<Map<String, String>> maps = new ArrayList<>();
         maps.add(sgyy);
         maps.add(sdxl);
         maps.add(xajh);
         //遍历
         for (Map<String, String> map : maps) {
             Set<String> strings = map.keySet();
             for (String key : strings) {
                 System.out.println(key + "===" + map.get(key));
             }
         }
     }
 }


在学习数组的时候数组有数组工具类Arrays。那么集合有没有集合工具类呢?  有呢:Collections

Collections成员方法
         public static <T > void sort (List < T > list):排序, 默认按照自然顺序
         public static <T > int binarySearch (List < ? > list, T key):二分查找
         public static <T > T max(Collection < ? > coll):获取最大值
         public static void reverse (List < ? > list):反转
         public static void shuffle (List < ? > list):随机置换

说了那么多,再来个干货游戏吧,哈哈(不过现在水平有限,没有学到页面化,只能是程序表示)

public class 斗地主 {
     @SuppressWarnings("unused")
     public static void main(String[] args) {
         //创建一个索引集合
 //        TreeMap<Integer,String> treeMap = new TreeMap<Integer,String>();
         HashMap<Integer,String> hashMap = new HashMap<Integer,String>();
         
         ArrayList<Integer> arrayList = new ArrayList<Integer>();
         String[] color= {"♥","♤","♣","♢"};
         String[] num= {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
         int index=0;
         for(String nums:num) {
             for(String colors:color) {
                 hashMap.put(index, colors.concat(nums));
                 arrayList.add(index);
                 index++;
             }
         }
         //手动加上大小王。
 //        System.out.println(index);
         hashMap.put(index,"☼");
         arrayList.add(index);
         index++;
         hashMap.put(index,"小王");
         arrayList.add(index);
         //洗牌
         Collections.shuffle(arrayList);
         Collections.shuffle(arrayList);
         Collections.shuffle(arrayList);
 //        创建手牌对象(集合);
         Set<Integer> 周星驰=new TreeSet<Integer>();
         Set<Integer> 刘德华=new TreeSet<Integer>();
         Set<Integer> 周润发=new TreeSet<Integer>();
         Set<Integer> 底牌=new TreeSet<Integer>();
         //发牌:
         /*
          * 周星驰:0  3  6  9....
          * 刘德华:1  4  7  10....
          * 周润发:2  5  8  11....
          */
         for(int x=0;x<arrayList.size();x++) {
             if(x>=arrayList.size()-3) {
                 底牌.add(arrayList.get(x));
             }else if(x%3==0) {
                 周星驰.add(arrayList.get(x));
             }else if(x%3==1) {
                 刘德华.add(arrayList.get(x));
             }else if(x%3==2) {
                 周润发.add(arrayList.get(x));
             }
         }
         //看牌,每个人拿着牌的索引去拍盒子里边找牌
         lookPoker("周星驰",周星驰,hashMap);
         lookPoker("刘德华",刘德华,hashMap);
         lookPoker("周润发",周润发,hashMap);
         lookPoker("底牌",底牌,hashMap);
     }
     public static void lookPoker(String name,Set<Integer> treeSet,HashMap<Integer,String> hashMap) {
         System.out.println(name);
         for(Integer index:treeSet) {
             System.out.print(hashMap.get(index)+"  ");
         }
         System.out.println();
     }
 }