集合之Map

来源:互联网 发布:2017淘宝活动大全 编辑:程序博客网 时间:2024/06/07 19:01

已实现的子类:
1、HashMap
底层数据结构是哈希表,可以存放null键和null值,该集合是线程不同步的,效率高,jdk1.2出现。
2、HashTable
底层数据结构是哈希表,不可以存放null键和null值,该集合是线程同步的,效率低,jdk1.0出现。
3、TreeMap
底层是二叉树数据结构,线程不同步,可以用于给Map中的键进行排序。

Map中取元素的方式:
1、Map中的取出方式
(1)Map.Entry:这是一种描述键值对之间的映射关系的一种特殊数据类型,可以指定泛型,而Entry接口是Map接口的一个静态子接口,又称为映射项,意指在Map存在后用来表示Map中键值的关系,而Map.Entry接口通常被一个内部类实现。。。。。通过map的entrySet方法来获取Map.Entry类型的Set集合,然后通过Set迭代器来获取Map.Entry对象,用这个对象调用其内部的getKey和getValue方法获取建和值。
(2)通过keySet方法获得一个存取key的Set集合,然后通过map的getKey方法获取这些键,通过map的get(key)方法获取对应的值。

下面用一个例子来实现这两种方法
exp1:

import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Set;class Student implements Comparable<Student>{    private String name;    private int age;    public Student(String name,int age) {        // TODO 自动生成的构造函数存根        this.name = name;        this.age = age;    }    public String getName() {        return name;    }    public int getAge() {        return age;    }    @Override    public String toString() {        // TODO 自动生成的方法存根        return super.toString();    }    //重写compareTo方法自定义排序规则    @Override    public int compareTo(Student s) {        // TODO 自动生成的方法存根        int num = new Integer(this.getAge()).compareTo(new Integer(s.getAge()));        System.out.println(this.name+"-compareTo-"+s.getName());        if(num == 0)            return this.getName().compareTo(s.getName());         return num;    }    //重写hashCode方法    @Override    public int hashCode(){        // TODO 自动生成的方法存根        return name.hashCode()+age*32;    }    //重写equals方法自定义元素唯一性标准    @Override    public boolean equals(Object obj) {        // TODO 自动生成的方法存根        if(!(obj instanceof Student))            throw new ClassCastException("类型不匹配");        Student s = (Student) obj;        return this.name.equals(s.name)&&this.age == s.age;    }   }public class MapTest1 {    public static void main(String[] args) {        Map<Student,String> map = new HashMap<Student,String>();        map.put(new Student("张三", 18), "上海");        map.put(new Student("李四", 19), "西安");        map.put(new Student("王五", 20), "火星");        /*        //第一种取出方式        Set<Student> keySet = map.keySet();        Iterator<Student> it = keySet.iterator();        while(it.hasNext()){            Student s = it.next();//key            String attr = map.get(s);            System.out.println(s.getName()+"-"+s.getAge()+":"+attr);        }        */        //第二种取出方式        Set<Map.Entry<Student, String>> set = map.entrySet();        for(Iterator<Map.Entry<Student, String>> it = set.iterator();it.hasNext();)        {            Map.Entry<Student, String> entry = it.next();            Student s = entry.getKey();            String attr = entry.getValue();            System.out.println(s.getName()+"-"+s.getAge()+":"+attr);        }    }}

这里写图片描述

看完这两种方法后再看一下这个例子中重写了equals和hashCode方法,当要指定元素唯一性时可能要涉及多个方面,而equals方法本身比较的是某个对象的一项内容,比如Integer和String对象,因此需要重写。然后重写hashCode方法保证元素唯一性主要是以实例为主,而不是对象本身,比如两个不同的对象拥有不同的哈希码直接存入,但此时实例却相同,从而省略了equals方法判断这一步,导致与实际情况不符。

但为什么要重写compareTo方法呢?因为当有多个对象要被存储时,此时存储的容器就有了多种选择,可以是哈希表、二叉树、数组等等,如果将多个对象存入了二叉树中,元素就必须被赋予排序规则,否则会抛出异常,所以为了保险起见需要定义比较器,通过实现Comparable或Comparator接口均可。


由于Map本身也是一个对象,而对象可以作为元素存到集合中,所以Map中也可以嵌套,当然该内部Map对象也可以根据其键值对的含义将其封装为一个类,然后将该类对象存入。下面通过两个例子说明这两种方法。

exp2:

import java.util.HashMap;import java.util.Iterator;/* * Map之间的嵌套 */public class MapTest1 {    public static void main(String[] args) {        HashMap<String,HashMap<Integer,String>> school = new HashMap<String,HashMap<Integer,String>>();             HashMap<Integer,String> class1 = new HashMap<>();        HashMap<Integer,String> class2 = new HashMap<>();        school.put("普通班", class1);        school.put("火箭班", class2);        class1.put(1, "张三");        class1.put(2, "李四");        class2.put(1, "王五");        class2.put(2, "赵六");        Iterator<String> it1 = school.keySet().iterator();        while(it1.hasNext()){            String cla = it1.next();//取班级的key            HashMap<Integer, String> claMap = school.get(cla);//取班级的值            System.out.println(cla);            Iterator<Integer> it2 = claMap.keySet().iterator();            while(it2.hasNext()){                int num = it2.next();                String name = claMap.get(num);                System.out.println(num+"::"+name);            }        }    }}

exp3:

import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;/* * Map存入对象 *  */public class MapTest2 {    public static void main(String[] args) {        HashMap<String, List<Student>> school = new HashMap<String,List<Student>>();        List<Student> rClass = new ArrayList<Student>();        List<Student> nClass = new ArrayList<Student>();        school.put("普通班", nClass);        school.put("火箭班", rClass);        nClass.add(new Student(1,"王五"));        nClass.add(new Student(2,"赵六"));        rClass.add(new Student(1,"张三"));        rClass.add(new Student(2,"李四"));        Iterator<String> it = school.keySet().iterator();        while(it.hasNext()){            String className = it.next();            List<Student> list = school.get(className);            System.out.println(className);            for(Student item : list){                System.out.println(item.getNum()+"::"+item.getName());            }        }    }}class Student{    private String name;    private int num;    public Student(int num,String name) {        this.name = name;        this.num = num;    }    public String getName() {        return name;    }    public int getNum() {        return num;    }}

对于TreeMap,如果存入对象并没有自然顺序或要按照给定顺序排序,必须要定义一个比较器来使元素有自然顺序,下面通过一个例子说明。
exp4:

import java.util.Comparator;import java.util.Iterator;import java.util.Map;import java.util.Set;import java.util.TreeMap;/* *  * 输入一个字符串,打印每个字符以及出现的次数并使字符倒序排序 * 输出格式为:字符(次数)字符(次数)... *  * 思路:(1)将字符串中的字符存到一个数组中,然后对数组遍历,如果当前元素在TreeMap中不存在 *      那么添加进去,并将该元素和其出现次数作为一对键值对;如果当前元素已存在,定义一个 *      累加器,在已存在次数基础上自加一次再存入TreeMap中,由于key值相同,所以以前的 *      记录将会被更新,第一种情况也是如此,只不过累加器是从零开始的。最后按照给定格式取出 *      存在Map中的元素。 *      (2)创建比较器自定义比较规则 */public class TreeMapTest {    public static String charCount(String str){        char[] ch = str.toCharArray();        TreeMap<Character, Integer> treeMap = new TreeMap<>(new Compare());        int count = 0;        for(int i=0;i<ch.length;i++){            if(!(ch[i]>='a'&&ch[i]<='z'||ch[i]>='A'&&ch[i]<='Z'))                continue;            Integer value = treeMap.get(ch[i]);            if(value!=null)                count=value;            count++;            treeMap.put(ch[i], count);            count=0;        }           //System.out.println(treeMap);        StringBuffer sb = new StringBuffer();        Set<Map.Entry<Character, Integer>> set = treeMap.entrySet();        Iterator<Map.Entry<Character, Integer>> it = set.iterator();        while(it.hasNext()){            Map.Entry<Character, Integer> entry = it.next();            sb.append(entry.getKey()+"("+entry.getValue()+")");        }        return sb.toString();    }    public static void main(String[] args) {        String str = charCount("aababcabcd");        System.out.println(str);    }   }//定义一个比较器,使字符按照原有顺序的倒序排列class Compare implements Comparator<Object>{    @Override    public int compare(Object obj1,Object obj2) {        // TODO 自动生成的方法存根        if(!(obj1 instanceof Character)||(obj2 instanceof Character))        {            Character ch1 = (Character) obj1;            Character ch2 = (Character) obj2;            int result = ch1.compareTo(ch2);            if(result>0)                return -1;            else if(result<0)                return 1;            return 0;        }        throw new RuntimeException("类型不匹配");    }}
0 0
原创粉丝点击