【Java】如何理解Java中的双列集合Map?

1 Map<K,V>接口

1.1 特点

  1. 双列集合一个元素包含俩值
  2. Key不可以重复,Value可以重复
  3. Key和Value一一对应
  4. Key和Value可以时任意类型

1.2 常用方法

public V put(K key, V value): 不重复返回null,重复返回value

	public static void main(String[] args) {
    
    
        Map<String, Integer> persons = new HashMap<>();
        persons.put("张三",19);
        Integer out1 = persons.put("李四", 20);
        Integer out2 = persons.put("李四", 30);
        System.out.println(out1);//不重复返回null
        System.out.println(out2);//重复返回原来的value=20
        System.out.println(persons);//{李四=30, 张三=19}
    }

public V remove(Object Key):指定键,删除键值对,返回删除键对应的值,键不存在则返回null

    public static void main(String[] args) {
    
    
        Map<String, Integer> persons = new HashMap<>();
        persons.put("张三",19);
        persons.put("李四", 20);
        Integer out1 = persons.remove("张三");
        System.out.println(persons);//{李四=20}
        System.out.println(out1);//19
        Integer out2 = persons.remove("王五");
        System.out.println(out2);//null
    }

public V get(Object Key):通过键来获取值

    public static void main(String[] args) {
    
    
        Map<String, Integer> persons = new HashMap<>();
        persons.put("张三",19);
        System.out.println(persons.get("张三"));//19
        System.out.println(persons.get("李四"));//null
    }

public boolean containsKey(Object Key):键是否存在

    public static void main(String[] args) {
    
    
        Map<String, Integer> persons = new HashMap<>();
        persons.put("张三",19);
        System.out.println(persons.containsKey("张三"));//true
        System.out.println(persons.containsKey("李四"));//false
    }

1.3 遍历Map集合

方法1:遍历键找值法

public static void main(String[] args) {
    
    
        Map<String, Integer> map = new HashMap<>();
        map.put("张三",19);
        map.put("李四",20);
        map.put("王五",21);
        
        //1. 取出Map的所有key存在Set中
        Set<String> set = map.keySet();

        //2.1 while遍历set,获取key,map.get获取value
        Iterator<String> it = set.iterator();
        while(it.hasNext()){
    
    
            String key = it.next();
            Integer value = map.get(key);
            System.out.println(key + " " + value);
        }

        //2.2 foreach法遍历
        for(String key: set){
    
    
            System.out.println(key + " " + map.get(key));
        }

    }

方法2: Entry键值对对象
Map接口中有一个内部接口Entry
作用:Map一创建,就在Map中创建一个Entry对象,用来记录键和值,得到二者的映射关系。(相当于结婚证)

  1. Set<Map.Entry<K, V>> entrySet() 把Map集合的多个Entry对象取出存在Set集合中。
  2. 遍历Set集合,获取每个Entry对象。
  3. getKey()获取Key,getValue()获取Value。
public static void main(String[] args) {
    
    
        Map<String, Integer> map = new HashMap<>();
        map.put("张三",19);
        map.put("李四",20);
        map.put("王五",21);
        
        //1. 取出Map的所有entry对象存在Set中
        Set<Map.Entry<String, Integer>>set = map.entrySet();

        //2.1 while遍历set,获取entry,再分别getKey和Value
        Iterator<Map.Entry<String, Integer>> it = set.iterator();
        while(it.hasNext()){
    
    
            Map.Entry<String, Integer> entry = it.next();
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key + " " + value);
        }

        //2.2 foreach法遍历
        for(Map.Entry<String, Integer> entry: set){
    
    
            System.out.println(entry.getKey() + " " + entry.getValue());
        }

    }

2 Map接口的实现类—— HashMap

2.1 特点

  1. 底层是哈希表(JDK1.8后:数组+链表/红黑树) 查询快
  2. 无序集合,存取无序

2.2 存储自定义类型键值

注意:因为Map集合要保证Key是唯一的,所以作为Key的元素必须重写hashCode方法equals方法,从而保证Key的唯一性。

public static void main(String[] args) {
    
    
        Map<Person, Integer> map1 = new HashMap<Person, Integer>();
        map1.put(new Person("李四",10),170);
        map1.put(new Person("李四",10),180);
        System.out.println(map1);
        //重写前输出:{Person{name='李四', age=10}=180, Person{name='李四', age=10}=170}
        //重写后输出:{Person{name='李四', age=10}=180}
    }

3 HashMap的子类——LinkedHashMap

3.1 特点

  1. 底层是哈希表+链表 保证迭代顺序
  2. 有序集合,存取有序

3.2 使用示例

public static void main(String[] args) {
    
    
        HashMap<String, Integer> map1 = new HashMap<String, Integer>();
        map1.put("a",1);
        map1.put("c",3);
        map1.put("b",2);
        System.out.println(map1);//存和取顺序不同 {a=1, b=2, c=3}
        LinkedHashMap<String, Integer> map2 = new LinkedHashMap<>();
        map2.put("a",1);
        map2.put("c",3);
        map2.put("b",2);
        System.out.println(map2);//存和取顺序相同{a=1, c=3, b=2}
    }

4 Map接口的实现类——Hashtable

4.1 Hashtable的特点

  1. 键和值都不可以为空。
  2. 最早的双列集合,JDK1.0就有。
  3. 它是单线程的,同步的,线程安全,速度慢。
  4. 底层是一个哈希表。
  5. 和vector(ArrayList)一样再JDK1.2后被HashMap取代了。
  6. Hashtable的子类Properties集合是唯一一个和IO流结合的集合。【仍活跃】

4.2 示例

    public static void main(String[] args) {
    
    
        Hashtable<String,String> ht = new Hashtable<>();
        HashMap<String, String> hm = new HashMap<>();
        hm.put(null,null);
        hm.put("a",null);
        hm.put(null,"b");
        System.out.println(hm);//{null=b, a=null}
//      ht.put(null,null);
//      报错:java.lang.NullPointerException
    }

5 Map集合练习

5.1 统计字符出现次数

遍历字符串:charAt加索引遍历 / toCharArray转为数组
for(int i = 0; i < str.length(); i++) —> str.charAt(i)
for(char c: str.toCharArray()) —> c

public static void main(String[] args) {
    
    
        Scanner sc = new Scanner(System.in);
        String str = sc.next();
        Map<Character, Integer> map = new HashMap<>();
        char[] strArray = str.toCharArray();
        for (int i = 0; i < strArray.length; i++) {
    
    
            if(!map.containsKey(strArray[i])){
    
    
                map.put(strArray[i],1);
            }else{
    
    
                int value = map.get(strArray[i]);
                map.put(strArray[i],++value);
            }
        }
        System.out.println(map);
    }

5.2 斗地主升级版-玩家牌有序

public static void main(String[] args) {
    
    
        //1. 准备牌面
        String[] colors = {
    
    "♥","♠","♦","♣"};
        String[] nums = {
    
    "2","A","K","Q","J","10","9","8","7","6","5","4","3"};
        HashMap<Integer, String> pocker = new HashMap<>();
        pocker.put(0,"BK");
        pocker.put(1,"SK");
        int count = 2;
        for(String num: nums){
    
    
            for(String color: colors){
    
    
                pocker.put(count++,color+num);
            }
        }
        System.out.println(pocker);
        
        //2. 洗牌:打乱编号
        Set<Integer> set = pocker.keySet();
        ArrayList<Integer> list = new ArrayList<>();
        list.addAll(set);
        Collections.shuffle(list);
        ArrayList<Integer> left = new ArrayList<>();
        ArrayList<Integer> p1 = new ArrayList<>();
        ArrayList<Integer> p2 = new ArrayList<>();
        ArrayList<Integer> p3 = new ArrayList<>();
        for (int i = 0; i < pocker.size(); i++) {
    
    
            Integer p = list.get(i);
            if(i>=51){
    
    
                left.add(p);
            }else{
    
    
                if(i%3 == 0){
    
    
                    p1.add(p);
                }else if(i%3 == 1){
    
    
                    p2.add(p);
                }else{
    
    
                    p3.add(p);
                }
            }
        }
        
        //3. 发牌:对编号排序 取出标号对应的值
        Collections.sort(p1);
        Collections.sort(p2);
        Collections.sort(p3);
        Collections.sort(left);

        ArrayList<String> player1 = new ArrayList<String>();
        ArrayList<String> player2 = new ArrayList<String>();
        ArrayList<String> player3 = new ArrayList<String>();
        ArrayList<String> dipai = new ArrayList<String>();
        for(Integer i : p1){
    
    
            player1.add(pocker.get(i));
        }
        for(Integer i : p2){
    
    
            player2.add(pocker.get(i));
        }
        for(Integer i : p3){
    
    
            player3.add(pocker.get(i));
        }
        for(Integer i : left){
    
    
            dipai.add(pocker.get(i));
        }
        
        //4. 看牌
        System.out.println(player1);
        System.out.println(player2);
        System.out.println(player3);
        System.out.println(dipai);
    }

6 JDK9对集合添加的优化

Java9中添加了几种集合工厂方法,更方便创建少量元素的集合、map实例。新的ListSetMap的静态工厂方法可以更方便地创建集合的不可变实例。
使用前提:集合中存储的元素个数已经确定,不再改变时使用
注意

  1. 只适用于ListSetMap三个接口
  2. 它是不能改变的集合,不可再用add和put
  3. 不可以在调用时含有相同元素

猜你喜欢

转载自blog.csdn.net/xd963625627/article/details/105290673
今日推荐