集合(5)----Map接口

一、Map接口概述                                                                                                                                          点击此处返回总目录

二、Map接口中常用集合概述

三、Map接口的常用方法

四、Map集合的遍历方式

五、HashMap练习

六、LinkedHashMap

七、Hashtable

 

 

 

 

一、Map接口概述

Map接口也是集合,但是与Collection不一样。Collection每次只能装进去一个对象,而Map集合每次存储两个对象(键值对)。

Collection接口和Map接口没有任何关系。

Map中的集合不能包含重复的键,每个键对应一个值。

 

二、Map接口中常用集合概述

Map接口中常用的集合为HashMap、LinkedHashMap。

1. HashMap<K,V> 存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。

2. LinkedHashMap<K,V>:HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构。通过链表结构可以保证元素的存取顺序一致;通过哈希表结构可以保证的键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。

3. Hashtable<K,V>:慢慢淘汰了。

 

 

三、Map接口的常用方法

1. public V put(K key, V value)                        //添加键值对。如果包含了该键,则替换对应的值。返回值一般为null,

                                                                           当存储重复键的时候,返回的是被覆盖的值。【例1】

2. public V get(Object key)                              //获取。如果没有这个键,返回null。【例2】

3. public boolean containsKey(Object key);    //看看是否包含这个键。【例4】

4. public V remove(Object key)                      //如果存在的话,移除。【例3】

5. int size()                                                      //返回有几个键值对。【例3】

 

 

例1:

package cn.itcast.demo01;

import java.util.HashMap;
import java.util.Map;

public class Test {
    public static void main(String[] args) {
        Map<String,Integer> map = new HashMap<String,Integer>();
        map.put("liupc", 22);
        Integer i1 = map.put("li", 23);
        System.out.println(i1);                    //null。存储元素一般都是返回null。
        System.out.println(map);                //{li=23, liupc=22}
        
        Integer i2 =map.put("li",11);
        System.out.println(i2);                    //23。当存储重复键的时候,返回的是被覆盖的值。
        System.out.println(map);                //{li=11, liupc=22}
        
    }
}

例2:

package cn.itcast.demo02;

import java.util.HashMap;
import java.util.Map;

public class Test {
    public static void main(String[] args) {
        Map<String,Integer> map = new HashMap<String,Integer>();
        map.put("liu",23);
        map.put("li",22);
        System.out.println(map);      //{li=22, liu=23}
        
        Integer i = map.get("liu");   
        System.out.println(i);            //23
        System.out.println(map);      //{li=22, liu=23}
        
        Integer i2 = map.get("wang");
        System.out.println(i2);          //null
        
    }
}

例3:

package cn.itcast.demo03;


import java.util.HashMap;
import java.util.Map;

public class Test {
    public static void main(String[] args) {
        Map<String,Integer> map = new HashMap<String,Integer>();
        map.put("liu",23);
        map.put("li",22);
        System.out.println(map);              //{li=22, liu=23}
        System.out.println(map.size());    //2
        
        Integer i1 = map.remove("liu");
        System.out.println(i1);                  //23
        System.out.println(map);              //{li=22}
        
        Integer i2 = map.remove("wang");
        System.out.println(i2);                 //null
        System.out.println(map);             //{li=22}       
    }
}

例4:

package cn.itcast.demo01;

import java.util.HashMap;
import java.util.Map;

public class Test4 {
    public static void main(String[] args) {
        Map<Integer, Integer> map = new HashMap<>();
        
        map.put(1,3);
        map.put(2,4);
 

        System.out.println(map.containsKey(1));  //true
        System.out.println(map.containsKey(3));  //false       
    }
}

 

 

四、Map集合的遍历方式

方式1:利用键获取值的方式。首先调用Map的keySet()方法,把Map中的所有键存储到一个Set中;然后就可以遍历Set,拿到key了;最后通过get操作获取value的值。【例1】

 

例1:

package cn.itcast.demo04;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Test {
    public static void main(String[] args) {
        Map<String,Integer> map = new HashMap<String,Integer>();
        map.put("liupc", 22);
        map.put("li", 23);
        map.put("wang",24);
        
        Set<String> set = map.keySet();                               //把key存储到一个set中。
        //使用迭代器遍历
        Iterator<String> it =  set.iterator();
        while(it.hasNext()){
            String key = it.next();
            Integer value = map.get(key);
            System.out.println(key + ":" + value);
        }
        //使用增强for循环遍历
        for(String i:set){
            Integer val = map.get(i);
            System.out.println(i+":"+val);
        }
        
    }
}

方式2:entrySet()方法。

       Map接口中又写了一个接口:Entry(中文翻译为"登记")。Entry是映射关系的接口。方便理解,可以把key-value想成一对夫妻,而Entry就是结婚证。【例2】

       Map接口中有方法entrySet(),通过这个方法可以得到一个Set集合,集合中存放的是Entry类型的对象(映射关系的对象,结婚证)。Entry接口的getKey()、getValue()方法可以得到key和value。意思就是每个Key-Value对有一个结婚证,entrySet()方法可以收走所有夫妻的结婚证。然后通过结婚证可以找到夫妻两人。【例2】【例3】

 

例2:Map()接口的源码

public interface Map<K,V> {

    ....

    Set<Map.Entry<K, V>> entrySet();       //通过调用Map的entrySet()方法,可以得到一个集合,集合中存放的是Entry类型的对象。

    interface Entry<K,V> {                          //Map接口中又写了一个接口Entry。表示映射关系。

        K getKey();                                       //Entry接口的对象可以调用getKey()方法获取key。

        V getValue();                                    //也可以获取value。

        ......

    }

    ....

}

例3:

package cn.itcast.demo05;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Test {
    public static void main(String[] args) {
        Map<String,Integer> map = new HashMap<String,Integer>();
        map.put("aa", 1);
        map.put("bb", 2);
        
        Set<Map.Entry<String,Integer>> set = map.entrySet();   //调用Map集合的entrySet()方法:将集合中的映射关系对象,存储到                                                                                                     Set中。
        
        //迭代器方式:
        Iterator<Map.Entry<String,Integer>> it = set.iterator();    //迭代Set集合。
        while(it.hasNext()){
            Map.Entry<String, Integer> entry = it.next();                //获取的Set集合的元素是映射关系的对象。
            System.out.println(entry.getKey() + ":"+entry.getValue());   //通过映射关系对象的getkey()、getValue()方法获取key、Value.
        }
        
        //增强for方式:
        for(Map.Entry<String, Integer> entry : set){
            System.out.println(entry.getKey() + ":"+entry.getValue());   
        }
        
    }
}

说明:

1. 这两种方式都要熟练。第一种用的多,第二种复杂一点。

2. 面试题:增强for可以遍历Map么?答:不可以。因为增强for循环是Collection的父接口Iterable提供的方法。而Map不在Iterable下。

                那为什么例3中,使用了增强的for遍历了Map呢?答:因为实际上使用增强for遍历了entry的set集合,并没有直接遍历Map。

 

 

五、HashMap练习

练习1.使用HashMap存储自定义的对象Person,并遍历。将Person对象当做值。

 

//Person.java

package cn.itcast.demo06;

public class Person {
    private String name;
    private int age;
    
    public Person() {}
    
    public Person(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;
    }
    
    public String toString(){
        return name + "..."+age;
    }
    
}

//Test.java

package cn.itcast.demo06;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class Test {
    public static void main(String[] args) {
        Person p1 = new Person("aaa",11);
        Person p2 = new Person("bbb",22);
        
        HashMap<String,Person> map = new HashMap<String,Person>();
        map.put("AAA",p1);
        map.put("BBB",p2);
        
        
        //遍历方式一:
        Set<String> set = new HashSet<String>();
        set =map.keySet();
        for(String str:set){
            System.out.println(str + "..."+map.get(str));
        }
        
        //遍历方式二
        Set<Map.Entry<String,Person>> set1= map.entrySet();
        for(Map.Entry<String,Person> entry:set1){
            System.out.println(entry.getKey() +"..."+entry.getValue());
        }
        
    }
}

//结果:

BBB...bbb...22
AAA...aaa...11
BBB...bbb...22
AAA...aaa...11

 

练习2.使用HashMap存储自定义的对象Person,并遍历。将Person对象当做key。

首先来看一下代码:

//Person.java

package cn.itcast.demo06;

public class Person {
    private String name;
    private int age;
    
    
    public Person() {}
    
    public Person(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;
    }
    
    public String toString(){
        return name + "..."+age;
    }
    
}

//Test.java

package cn.itcast.demo07;
import java.util.HashMap;
import java.util.Set;

import cn.itcast.demo06.Person;

public class Test {
    public static void main(String[] args) {
        HashMap<Person,String> map= new HashMap<Person,String>();
        
        map.put(new Person("aaa",11), "haha");
        map.put(new Person("aaa",11), "haha");              //这两个Person对象都是新new的,不是同一个对象。
        
        Set<Person> set = map.keySet();
        for(Person p :set){
            System.out.println(p + ".." +map.get(p));
        }
        
    }
}

运行结果:

aaa...11..haha

aaa...11..haha

 

运行结果发现,“同一个”key出现了两次。这不符合我们的期望。我们期望name和age都相等时,就认为是同一个key,在map中只能存一次。

为了能够达到我们的效果,应当重写Person的hashCode()方法和equals()方法。

 

//Person.java

package cn.itcast.demo08;

public class Person {
    private String name;
    private int age;
    
    
    public Person() {}
    
    public Person(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;
    }
    
    public String toString(){
        return name + "..."+age;
    }
    
    public int hashCode(){                                         //熟练之后,可以自动生成重写hashCode()的代码。
        String str = name + age;
        return str.hashCode();
    }
    
    public boolean equals(Object obj) {                    //熟练之后,可以自动生成重写equals()的代码。
        if(obj == null){
            return false;
        }
        if(this == obj){
            return true;
        }
        
        if (obj instanceof Person){
            Person p = (Person)obj;
            
            return name.equals(p.name) && age == p.age;
        }else{
            return false;
        }
        
    }
    
}

//Test.java

package cn.itcast.demo08;

import java.util.HashMap;
import java.util.Set;

public class Test {
    public static void main(String[] args) {
        HashMap<Person,String> map= new HashMap<Person,String>();
        
        map.put(new Person("aaa",11), "haha");
        map.put(new Person("aaa",11), "hehe");
        
        Set<Person> set = map.keySet();
        for(Person p :set){
            System.out.println(p + ".." +map.get(p));
        }
        
    }
}

运行结果:

aaa...11..hehe

 

六、LinkedHashMap

LinkedHashMap继承自HashMap。是有顺序的,存进去什么顺序,遍历就是什么顺序。

 

例:

package cn.itcast.demo09;

import java.util.LinkedHashMap;

public class Test {
    public static void main(String[] args) {
        LinkedHashMap<String,Integer> map =new LinkedHashMap<String,Integer>(); 
        map.put("bbb", 32);
        map.put("aaa", 22);
        map.put("ccc", 11);
        
        for(String s:map.keySet()){
            System.out.println(s+"..."+map.get(s));
        }    
    }
}

运行结果:

bbb...32
aaa...22
ccc...11

 

 

 

七、Hashtable

Hashtable是Map接口的又一个实现类。

底层数据结构也是哈希表。特点和HashMap是一样的。

与HashMap的区别是:HashMap是线程不安全的,运行速度快;Hashtable是线程安全的,运行速度慢。所以,Hashtable的命运和Vector集合一样,从JDK1.2开始,Hashtable被更先进的HashMap取代。已经慢慢被抛弃,郁郁而终了~

 

还有一个区别,一定要知道,面试的时候可能会问:

HashMap 允许存储null值,null键。Hashtable不允许存储null值、null键。【例1】

 

虽然Hashtable不怎么用了,但是他的子类Properties依然还活跃在开发舞台。他可以和后面的IO流配合,实现数据的持久存储。等到IO的时候单独讲~

 

例1:

package cn.itcast.demo10;

import java.util.HashMap;
import java.util.Hashtable;

public class Test {
    public static void main(String[] args) {
        HashMap<String,String> map = new HashMap<String,String>();
        map.put(null, "aa");
        map.put("11", null);
        System.out.println(map.get(null));         //aa
        System.out.println(map.get("11"));        //null
        
        Hashtable<String,String> table = new Hashtable<String,String>();
        table.put("11", "aa");
        //table.put(null, "bb");                            //这句错误。不能以null为键。
        //table.put("22",null);                             //这句错误。不能以nul为值。
        System.out.println(table.get("11"));       //aa
        //System.out.println(table.get(null));
        //System.out.println(table.get("22"));
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值