Map集合

     * 1.Map集合中存储的是一对儿元素。键和值。之间存在着对应关系。

     * 2.必须要保证键的唯一性。

     * 3.如果存储键相同,值会覆盖。



    特点:

        1,存储的都是键值对。

        2,要保证键的唯一性。

    

    存的方式:put(key,value);

        取的方式:keySet(),entrySet(),values();

        原理:就是将map集合转成set集合或者Collection集合,再通过Iterator取出。


    Map

        |--Hashtable:哈希表结构,同步的。null不可以作为键和值。

        |--HashMap:哈希表结构,不同步的。替代了Hashtable。允许null作为键和值。

        |--TreeMap:二叉树结构,不同步的,可以对map集合中的键进行排序。排序需要比较大小。

                排序方式有两种:1.元素自身具有比较性

                               2.容器构造器中传入一个比较器

    


集合框架-Map-常见方法

put(K key, V value) 
    将指定的值与此映射中的指定键关联(可选操作)。

返回: 

返回与 key 相关联的先前值,如果 key 没有映射关系,则返回 null(返回 null 可能还表示映射以前将 null 与指定键关联)


get(Object key) 
  

返回: 

指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null



    @Test
    public void test1(){
		/*
         * 需求:将学号和对应的学生姓名进行存储。
         */
        Map<Integer,String> map = new HashMap<Integer,String>();
        //存储键值对。
        System.out.println(map.put(2,"小花"));//之前与 key 关联的值,如果没有针对 key 的映射关系,则返回 null
        System.out.println(map.put(2,"麻子"));//小花,麻子之前是小花
        map.put(6,"赵六");
        map.put(1,"王五");
        System.out.println(map);//并没有排序,并且不是有序。2=麻子,“小花”被覆盖
        System.out.println(map.get(1));//王五
    }
测试结果:
    null
    小花
    {1=王五, 2=麻子, 6=赵六}
    王五	


集合框架-Map-keySet方法

Set底层用的是Map集合的Key

//    * 获取Map中的所有键值对。
//    * Map取出所有元素的原理:将map先转成set,再使用迭代器。
//    * 
	
	@Test
	public void test2(){
		  Map<String,String> map = new HashMap<String,String>();
	        
	        map.put("zhangsan","北京");
	        map.put("lisi","上海");
	        map.put("wangwu","成都");
	        map.put("zhaoliu","广州");
	        System.out.println(map);
 
	        //第一种方式:
	        //获取map集合中的键的集合。keySet();
	        Set<String> keySet = map.keySet();
	        
	        //通过set集合获取迭代器。
	        Iterator<String> it = keySet.iterator();
	        
	        while(it.hasNext()){
		        String key = it.next();
		        String value = map.get(key);
		        System.out.println(key+":"+value);
	        }
	}


集合框架-Map-entrySet方法&values方法

接口 Map.Entry<K,V>Entry接口是Map接口的内部接口,因为要访问Map接口中的成员变量,所以就定在内部了,而且它和Map的关系是,先有Map接口中的成员变量,之后才有了Entry接口,表示成员变量之间的关系,所以就定在了里面。

	@Test
	public void test3(){
		Map<String,String> map = new HashMap<String,String>();
		
		map.put("zhangsan","北京");
		map.put("lisi","上海");
		map.put("wangwu","成都");
		map.put("zhaoliu","广州");
		System.out.println(map);

	//第二种方式:
		//获取map集合中所有的键值关系集合。entrySet,键值关系的类型是 Map.Entry.
		
		Set<Map.Entry<String, String>> entrySet = map.entrySet();
		
		//迭代器取出所有的关系对象。
		Iterator<Map.Entry<String, String>> it = entrySet.iterator();
		while(it.hasNext()){
			
			Map.Entry<String, String> me = it.next();
			String key = me.getKey();
			String value = me.getValue();
			
			System.out.println(key+"::"+value);
		}

	}
	@Test
	public void test4(){
		Map<String,String> map = new HashMap<String,String>();
		
		map.put("zhangsan","北京");
		map.put("lisi","上海");
		map.put("wangwu","成都");
		map.put("zhaoliu","广州");
		System.out.println(map);
		
		//第三种方式:获取值的集合。values();
		
		Collection<String> values = map.values();
		
		Iterator<String> it = values.iterator();
		while(it.hasNext()){
			String value = it.next();
			System.out.println(value);
		}
		
	}

Map-HashMap存储自定义对象

 

package cn.itcast.p1.map;
 
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
 
import cn.itcast.bean.Student;
 
public class HashMapDemo {
    public static void main(String[] args) {
     
        /*
         * 将学生对象存储和学生的归属地存储到HashMap集合中。
         * 对于学生对象,同姓名同年龄视为同一个人。
         */
        
        
        //1,创建一个HashMap集合对象。
        HashMap<Student,String> hm = new HashMap<Student,String>();
        
        //2,将学生对象和归属地存储到集合中。
        hm.put(new Student("xiaoming",20),"北京");
        hm.put(new Student("abc",20),"成都");
        hm.put(new Student("wangcai",20),"广州");
        hm.put(new Student("caige",20),"上海");
        hm.put(new Student("wangcai",20),"铁岭");
        
        //3,取出map集合中所有的元素。获取Map中键的集合,通过keySet方式。
        //Set<Student> keySet = hm.keySet();
        //Iterator<Student> it = keySet.iterator();
        Iterator<Student> it = hm.keySet().iterator(); 
        while(it.hasNext()){
            Student key = it.next();
            String value = hm.get(key);
            System.out.println(key.getName()+":"+key.getAge()+":"+value);
        }
    }
}


//比较两个对象是否一样,重写hashcode方法 和 equals方法
package cn.itcast.bean;
 
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;
    }
    
    
    /**
     * 覆盖hashCode方法
     * @return
     */
    @Override
    public int hashCode() {
    
        final int NUMBER = 31;//对31这个数字进行命名定义。增强了阅读性。
    
        return name.hashCode()+age*NUMBER;
    }
    
    
    
    /**
     * 覆盖equals方法
     * @return
     */
    @Override
    public boolean equals(Object obj) {
    
        if(!(obj instanceof Student))
            throw new NotTypeException("错误的类型");
    
        Student stu = (Student)obj;
        return this.name.equals(stu.name) && this.age == stu.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 + "]";
    }
}



Map-TreeMap存储自定义对象

package cn.itcast.p1.map;
 
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
 
import cn.itcast.bean.Student;
import cn.itcast.p2.comparator.ComparatorByName;
 
public class TreeMapDemo {
     
    public static void main(String[] args) {
         
        //1,创建TreeMap集合。
        //设置比较器,定义排序方式:map的key的排序方式根据对象的name值的自然排序
        TreeMap<Student,String> tm = new TreeMap<Student,String>(
            new Comparator<Student>(){
                @Override
                public int compare(Student o1, Student o2) {
                    int temp = o1.getName().compareTo(o2.getName());
                    return temp==0?o1.getAge()-o2.getAge(): temp;
                }
            }  
         });
        tm.put(new Student("xiaoming",26),"北京");
        tm.put(new Student("abc",24),"成都");
        tm.put(new Student("wangcai",21),"广州");
        tm.put(new Student("caige",27),"上海");
        tm.put(new Student("wangcai",21),"铁岭");
        // 取出集合中的元素。获取Map集合中所以键值关系集合方法entrySet()
        //Set<Map.Entry<Student,String>> entrySet = tm.entrySet();
        //Iterator<Map.Entry<Student,String>> it = entrySet.iterator();
        Iterator<Map.Entry<Student,String>> it = tm.entrySet().iterator();
        while(it.hasNext()){
            Map.Entry<Student, String> me = it.next();
            Student key = me.getKey();
            String value = me.getValue();
            System.out.println(key.getName()+"::"+key.getAge()+"::"+value);
        }
    }
 
}


Map-什么时候用Map

     * 什么时候用map集合?

     * 在分析需求中,如果出现了映射关系,就要先想到具备对应关系的容器。

     * 比如 数组,listmap

     * 如果对应关系的一方是有序的数字,可以考虑数组和list,元素固定考虑数组,不固定考虑list

     * 如果对象关系的一方没有有序的数字,就要想到map

     *

     * 通常这些对应关系的容器都可以用于查表法。  

 

 
package cn.itcast.test;
 
import java.util.HashMap;
import java.util.Map;
 
public class Test {
 
    public static void main(String[] args) {
        String week = getCnWeek(3);
        String enweek = getEnWeek(week);
        System.out.println(week);
        System.out.println(enweek);
    }
    
    /**
     * 通过中文获取英文。 
     * @param num
     * @return 返回的是cnweek参数对应的英文表示方式。
     * 如果没有对应返回 null。
     */
    public static String getEnWeek(String cnweek){
        /*
         * 创建一个表。存储中英对应星期。
         */
        Map<String,String> weekMap = new HashMap<String,String>();
        weekMap.put("星期一", "Monday");
        weekMap.put("星期二", "Tuesday");
        weekMap.put("星期三", "Wednesday");
        weekMap.put("星期四", "Thursday");
        weekMap.put("星期五", "Friday");
        weekMap.put("星期六", "Saturday");
        weekMap.put("星期日", "Sunday");
        return weekMap.get(cnweek);
   }
        
   public static String getCnWeek(int num){
        //定义一个表。
        String[] weeks = {"","星期一","星期二","星期三","星期四","星期五","星期六","星期日"};
        return weeks[num];
    }
}


 

Map-练习-字母次数

 /*作业:
 * "ert+yuiodf8g.hjkt"想要知道每个字母出现的次数。
 * a(3)b(5)c(1)e(6).....友情提示:当需求中有对应关系时,先要考虑map集合。
 * 
 * 思路:
 * 1,字母很多,必须要进行存储。存储就需要使用容器。
 * 2,哪个容器呢?数组,不合适,长度不确定。StringBuffer,不合适,要对单个字母操作。
 *    Collection,好像也不太合适,存储了字母后,次数咋办?
 * 3,发现字母和次数之间存在着对应关系,所以可以使用map集合。
 * 具体用哪个子类对象呢?发现要求的结果中abc等出现是有顺序的。所以可考虑使用TreeMap。
 * 4,map集中,存储的就是字母和对应的次数,字母作为键。map作为表。
 *   将字符串中的每一个字母都去查表。如果该字母没查找对应的次数,就将该字母和1存储到表中。
 *   如果查到次数,将次数加+1后,将该字母和次数存储到表中。
 * 
 */

 
package cn.itcast.test;
 
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
 
public class Test2 {
    public static void main(String[] args) {
        String str = "erAt+yuAeioCrdCfe8g.hyjkt";
        str = sortChar(str);
        System.out.println(str);
    
    }
    
    public static String sortChar(String str){
    
        //1,定义一个存储字母和次数的表。TreeMap.
        Map<Character,Integer> map = new TreeMap<Character,Integer>();
        
        //2,将字符串转成字符数组。
        char[] chs = str.toCharArray();
        
        //3,对数组进行遍历。
        for(int x=0; x<chs.length; x++){
        
        if(!isLetter(chs[x])){
            continue;//不是字母,回去循环,下面的语句不要执行
        }
        //将遍历到的字符作为键。去查表。获取对应的次数。
        Integer value = map.get(chs[x]);
        int count = 0;
        if(value!=null){
            count = value;
        }
        count++;
        
        //将字母和对应的次数存储到map集合中。
        map.put(chs[x], count);
    
    }
    
    return mapToString(map);
    
    }
     
    /*
     * 将map集合转成指定格式的字符串。键(值)键(值)....
     */
    private static String mapToString(Map<Character, Integer> map) {
    
        //元素很多,最终要变成字符串。废话吗?不用废话,StringBuilder正好ok。
        StringBuilder sb = new StringBuilder();
        
        //遍历map。
        Iterator<Map.Entry<Character, Integer>> it = map.entrySet().iterator();
        
        while(it.hasNext()){
        
            Map.Entry<Character, Integer> me = it.next();
            
            Character key = me.getKey();
            Integer value = me.getValue();
             
            //StringBuilder的增加字符串的方法append()
            sb.append(key+"("+value+")");
        }
        
        return sb.toString();
    }
     
    /*
     * 判断字符是否是字母。
     */
    private static boolean isLetter(char c) {
    
        return c>='a' && c<='z' || c>='A' && c<='Z';
    }
 
}