JAVA--Map集合详解

2021-04-25 17:45:14 浏览数 (1)

参考链接: Java Map接口

特点:该集合存储键(key)值(value)对,一对一对往里存,而且要保证键(key)的唯一性。 

       Map集合和Set集合很像,其实Set集合底层就是使用了Map集合。 

什么时候使用Map集合: 

    当数据之间存在映射关系时,优先考虑Map集合。 

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 containsKey(Object key):如果此映射包含指定键的映射关系(是否包含该键),则返回 true。 

boolean containsValue(Object value):如果此映射将一个或多个键映射到指定值(是否包含该值),则返回 true。 

boolean isEmpty():如果此映射未包含键-值映射关系,该map集合为空,则返回 true。 

4.获取 

V get(Object key):返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。 

int size():返回此映射中的键-值映射关系(键值对)数。 

Collection<V> values():返回此映射中包含的值的 Collection 视图(集合)。 

重点取出方式: 

Set<K> keySet():返回此映射中包含的键的 Set 视图(集合)。 

Set<Map.Entry<K,V>> entrySet():返回此映射中包含的映射关系的 Set 视图(集合)。 

练习 

class MapDemo{

    public static void main(String[] args){

        Map<String,String> map=new HashMap<String,String>();

        // 添加元素,如果出现相同的键,那么后添加的值会覆盖原有键对应值。

        // put方法会返回被覆盖的值。

        System.out.println("put:" map.put("01","zhangsan1"));

        System.out.println("put:" map.put("01","wangwu"));

        map.put("02","zhangsan2");

        map.put("03","zhangsan3");

        System.out.println("containsKey:" map.containsKey("022"));

        System.out.println("remove:" map.remove("02"));

        System.out.println("get:" map.get("023"));

        map.put("04",null);    // 一般值不要存储null,没有意义

        System.out.println("get:" map.get("04"));

        // 可以通过get方法的返回值来判断一个键是否存在。通过返回null来判断

        // 获取map集合中所有的值

        Collection<String> coll=map.values();

        System.out.println(coll);

        System.out.println(map);

    }

}

Hashtable 

底层是哈希表数据结构。 

特点:不可以存入null键null值,该集合是线程同步的,JDK1.0出现,效率低。 

HashMap 

底层是哈希表数据结构。 

特点:允许使用null值和null键,该集合是线程不同步的,JDK1.2出现,效率高。 

Map集合的两种取出方式 

Map集合的取出原理:将Map集合转成Set集合,再通过迭代器取出。 

Set<K> keySet():

将Map集合中所有的键存入到Set集合。因为Set集合具备迭代器,所以可以通过迭代方法取出所有的键,再根据get()方法,获取每一个键对应的值。 

      2.Set<Map.Entry<K,V>> entrySet(): 

将Map集合中的映射关系存入到了Set集合中,而这个映射关系的数据类型就是:Map.Entry。 

   Map.Entry:其实Entry也是一个接口,它是Map接口中的一个内部接口。  

interface Map{

    public static interface Entry{

        public abstract Object getKey();

        public abstract Object getValue();

    }

}

class HashMap implements Map{

    class Hahs implements Map.Entry{

        public Object getKey(){};

        public Object getValue(){};

    }

}

案例  

import java.util.*;

class MapDemo2{

    public static void main(String[] args){

    Map<String,String> map=new HashMap<String,String>();

    map.put("02","zhangsan2");

    map.put("03","zhangsan3");

    map.put("01","zhangsan1");

    map.put("04","zhangsan4");

    /*// 方法一:通过keySet()获取Map集合元素

    // 先获取Map集合的所有键的Set集合,通过keySet()方法获取到

    Set<String> keySet=map.keySet();

    // 有了键的Set集合,就可以获取其迭代器

    Iterator<String> it=keySet.iterator();

    while(it.hasNext()){

        String key=it.next();

        // 有了键可以通过Map集合的get()方法获取其对应的值

        String value=map.get(key);

        System.out.println("Key:" key ",value:" value);

    }*/

    // 方法二:通过entrySet()获取Map集合元素

    // 先获取Map集合中的映射关系的Set集合,通过entrySet()方法获取到

    Set<Map.Entry<String,String>> entrySet=map.entrySet();

    // 有了键的Set集合,就可以获取其迭代器

    Iterator<Map.Entry<String,String>> it=entrySet.iterator();

    while(it.hasNext()){

        Map.Entry<String,String> me=it.next();

        // 有了映射关系可以通过映射关系的getKey()和getValue()方法获取其对应的键值

        String key=me.getKey();

        String value=me.getValue();

        System.out.println("Key:" key ",value:" value);

    }

    }

}

练习 

import java.util.*;

/*

目标:

每一个学生都有对应的归属地。

学生Student,地址String。

学生属性:姓名,年龄。

注意:姓名和年龄相同的视为同一个学生。

保证学生的唯一性。

思路:

1.描述学生;

2.定义Map容器。将学生(唯一性)作为键,地址作为值,存入;

3.获取Map集合中的元素。

*/

class MapTest{

    public static void main(String[] args){

    Map<Student,String> map=new HashMap<Student,String>();

    map.put(new Student("lisi1",21),"beijing");

    map.put(new Student("lisi1",21),"tainjin");

    map.put(new Student("lisi2",22),"shanghai");

    map.put(new Student("lisi3",23),"nanjing");

    map.put(new Student("lisi4",24),"jinan");

    // 第一种取出方式keySet

    Set<Student> keySet=map.keySet();

    Iterator<Student> it=keySet.iterator();

    while(it.hasNext()){

        Student stu=it.next();

        String addr=map.get(stu);    

        sop(stu "..." addr);

    }

    // 第二种取出方式entrySet

    Set<Map.Entry<Student,String>> entrySet=map.entrySet();

    Iterator<Map.Entry<Student,String>> it2=entrySet.iterator();

    while(it2.hasNext()){

        Map.Entry<Student,String> me=it2.next();

        Student stu=me.getKey();

        String addr=me.getValue();

        sop(stu "......" addr);

    }

    }

    // 打印语句

    public static void sop(Object obj){

        System.out.println(obj);

    }

}

// 学生类,保证学生的唯一性

class Student implements Comparable<Student>{    

    private String name;

    private int age;

    public Student(String name,int age){

        this.name=name;

        this.age=age;

    }

    // 防止该对象往二叉树数据类型集合中存储报异常,应使该对象具备可比性

    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;

    }

    // 保证学生的唯一性

    public int hashCode(){

        return this.name.hashCode() age*35;

    }

    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 int getAge(){

        return age;

    }

    public String toString(){

        return name ":" age;

    }

}

TreeMap 

底层是二叉树(红黑树)数据结构。 

特点:线程不同步,可以同时给Map集合中的键进行排序。 

案例 

import java.util.*;

/*

目标:

每一个学生都有对应的归属地。

学生Student,地址String。

学生属性:姓名,年龄。

注意:姓名和年龄相同的视为同一个学生。

保证学生的唯一性。

并且对学生对象大的年龄进行升序排序。

思路:

因为数据是以键值对形式存在的,

所以要使用可以排序的Map集合:TreeMap。

1.描述学生;

2.定义Map容器。将学生(唯一性)作为键,地址作为值,存入;

3.获取Map集合中的元素。

*/

class MapTest2{

    public static void main(String[] args){

    TreeMap<Student,String> tm=new TreeMap<Student,String>(new StuNameComparator());     

    tm.put(new Student("lisi1",21),"beijing");

    tm.put(new Student("blisi3",23),"nanjing");

    // tm.put(new Student("lisi1",21),"tainjin");

    tm.put(new Student("alisi4",24),"jinan");

    tm.put(new Student("lisi2",22),"shanghai");

    Set<Map.Entry<Student,String>> entrySet=tm.entrySet();

    Iterator<Map.Entry<Student,String>> it=entrySet.iterator();

    while(it.hasNext()){

        Map.Entry<Student,String> me=it.next();

        Student stu=me.getKey();

        String addr=me.getValue();

        sop(stu "......" addr);

    }

    }

    // 打印语句

    public static void sop(Object obj){

        System.out.println(obj);

    }

}

// 按照学生姓名排序,当对象本身具有比较性,但还需另一种比较,

// 可以定义比较器,在集合初始化时传入比较器,当有两种比较方式时默认按照比较器方法排序

class StuNameComparator implements Comparator<Student>{

    public int compare(Student s1,Student s2){

        int num =s1.getName().compareTo(s2.getName());

        if(num==0)

            return new Integer(s1.getAge()).compareTo(s2.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;

    }

    // 防止该对象往二叉树数据类型集合中存储报异常,应使该对象具备可比性

    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;

    }

    // 保证学生的唯一性

    public int hashCode(){

        return this.name.hashCode() age*35;

    }

    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 int getAge(){

        return age;

    }

    public String toString(){

        return name ":" age;

    }

练习 

核心思想原理图 

import java.util.*;

/*

目标:

"sdfgzxcvasdfxcvdf"获取该字符串中的字母出现的次数。

希望打印结果:

a(1)c(2)……

通过结果发现,每一个字母都有对应的次数。

说明字母和次数之间存在映射关系。

什么时候使用Map集合:

    当数据之间存在映射关系时,优先考虑Map集合。

思路:

1.将字符串转换成字符数组。因为要对每一个字母进行操作。

2.定义一个Map集合。而且打印结果字母有顺序,所以使用TreeMap集合。

3.遍历字符数组。

    将每一个字母作为键去查Map集合元素。

    如果返回null,将该字母和1存入到Map集合中。

    如果返回不是null,说明该字母在Map集合已经存在并有对应次数(值)。

    那么就获取该次数并进行自增,然后将该字母和自增后的次数存入到Map集合中。原理:覆盖已有键对应的值。

4.将Map集合中的数据变成指定的字符串形式返回。

*/

class MapTest3{

    public static void main(String[] args){

        String s="sdfgzxcv,asdfxcv df";

        String result=charCount(s);

        System.out.println(result);

    }

    public static String charCount(String str){

        char[] chs=str.toCharArray();

        TreeMap<Character,Integer> tm=new TreeMap<Character,Integer>();

        int count=0;

        for(int x=0;x<chs.length;x ){

            // 检查该字符是否为字母,如果不是跳出本次循环

            if(!(chs[x]>='a' && chs[x]<='z' || chs[x]>='A' && chs[x]<='Z'))

                continue;

            Integer value=tm.get(chs[x]);

            if(value!=null)

                count = value;

            count ;

            tm.put(chs[x],count);

            count=0;

            /*// 繁复写法

            if(value==null){

                tm.put(chs[x],1);

            }else{

                value=value 1;

                tm.put(chs[x],value);

            }*/

        }

        // System.out.println(tm);

        StringBuilder sb=new StringBuilder();

        Set<Map.Entry<Character,Integer>> entrySet=tm.entrySet();

        Iterator<Map.Entry<Character,Integer>> it=entrySet.iterator();

        while(it.hasNext()){

            Map.Entry<Character,Integer> me=it.next();

            char key=me.getKey();

            int value=me.getValue();

            sb.append(key "(" value ") ");

        }

        return sb.toString();

    }

}

0 人点赞