Java 进阶——集合体系详解之Map体系键值对集合

引言

前两篇博文 Java 集合体系详解——List体系有序集合 Java 集合体系详解——Set体系无序不重复集合总结了下List和Set体系集合的用法,这一篇主要总结下一个新的体系Map

一Map体系的访问方式

Map的访问也和HashSet的特点一样是无需的,Map体系与Set体系不同并不实现Iterator接口,当然也不会具有迭代器,那么Map集合怎么访问呢?间接通过Set的迭代器,Map集合访问方式主要有两种:keySetentrySet

  1. keySet:将Map中所有的键存入到Set集合,再借助Set的迭代器Iterator取出所有的键,最后再根据get方法获取到键对应的值。
Map<T,T> map=new HasMap<T,T>()
Set<T> set=map.keySet();//得到Set集合
Iterator<T> it=set.iterator();//得到Set集合的迭代器
while(it.hasNext()){
    String key=it.next();//通过迭代器获取键
    String value=map.get(key);//map根据键获取对应的值
}
  1. entrySet:将Map集合的映射关系Map.Entry存入到Set集合中,映射关系的数据类型就是Map.Entry。
/*
Map.Entry:其实Entry是Map接口中的一个内部接口(因为能加static修饰符只能是成员变量,所以只能是成员接口),因为只能先有Map集合才有映射关系,而映射关系是直接处理成员数据的,所以设计为内部接口。
interface Map{
    public static interface Entry{
        public abstract Object getKey();
        ...
    }
}
//嵌套接口的实现
class HashMaps implements Map{
    class Maps implements Map.Entry{
        public Object getKey();
        ...
    }
}*/

Set<Map.Entry<T,T>> entrySet=map.entrySet();//得到Set集合
Iterator<Map.Entry<T,T>> it=entrySet.iterator();//得到Set集合的迭代器
while(it.hasNext()){
    Map.Entry<T,T> m=it.next();//通过迭代器获取映射关系
    String key=m.getKey();//通过映射关系获取key
    String value=map.getValue(key);
}

二Map体系集合之HashTable(已基本被HasMap替代)

哈希表HashTable实现了Map接口,该哈希表将键映射到对应的值,该集合是线程同步的。任何非null对象都可以作为键Key或者值Value,换言之不允许存入null键null值。为了能成功在哈希表中存储和获取对象,用作键的对象必须实现hashCodeequals方法。

三Map体系集合之HashMap

HashMap底层数据结构也是哈希表,除了非同步和允许使用null键和null值、效率比较高以外,其他功能和HashTable类相同。
要保存到Map集合的对象完成三步工作:实现Comparable<对象>、覆写compareTohashCodeequals方法,至于原因吗,因为哈希体系。

class  Person implements Comparable<Person>{
    private String name;
    private int age;

    Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    public int compareTo(Person s){
        int num=new Integer(this.age).compareTo(new Integer(s.age));
        if(num==0){
            return this.name.compareTo(s.name);
        }
        else{
            return num;
        }
    }
    //为了去除重复必须重新构造hashCOde
    public int hashCode()
    {
        return name.hasCode()+age*37;
    }

    //当哈希值相同的时候才会执行
    public boolean equals(Object obj){
        if(!(obj instanceof Person)){
            throw new ClassCastException("类型不匹配");
        }
        Person p=(Person)obj;
        return this.name.equals(p.name) && this.age==p.age;
    }
    public String toString(){
        return "姓名:"+name+"年龄:"+age;
    }
}
//把Person对象保存到HasMap中,以Person对象为键,对应的籍贯为值,姓名和年龄相同就认为是相同的人,需要保持唯一性
public static void main(String[] args){
    Map<Person,String> map=new HashMap<Person,String>();
    map.put(new Person("zhang3",18),"beijing");
    map.put(new Person("zhang4",19),"didu");
    map.put(new Person("zhang5",21),"modu");
    //map.put(new Person("zhang5",21),"将要替换掉modu");若已经保存了(new Person("zhang5",21),"modu");再put(new Person("zhang5",21),"将要替换掉modu"),由于已经保存了(new Person("zhang5",21))再put时会替换原来的值变成新的值
//第一种keySet方式遍历
Set<Person> set=map.keySet();
Iterator<Person> it=set.iterator();//得到Set集合的迭代器
while(it.hasNext()){
    Person key=it.next();//通过迭代器获取键
    String value=map.get(key);//map根据键获取对应的值
    System.out.println(key.toString()+":"+value);
    }
//第二种方式entrySet
Set<Map.Entry<Person,String>> entrySet=map.entrySet();
Iterator<Map.Entry<Person,String>> iter=entrySet.iterator();//得到Set集合的迭代器
while(iter.hasNext()){
    Map.Entry<Person,String> pa=iter.next();//通过迭代器获取键
    Person key=pa.getKey();//获取键
    String value=pa.getValue();
    System.out.println(key.toString()+":"+value);
}
}

四Map体系集合之TreeMap

TreeMap是可以排序的Map集合,TreeMap底层数据结构是二叉树,线程不同步,可以用于给Map中的键Key排序,可以通过compareTo方法来排序,也可以通过传入比较器构造Map集合来覆盖掉comareTo方法来实现排序

1例:把Person对象保存到TreeMap,并按照姓名、年龄排序

class  Person implements Comparable<Person>{
    private String name;
    private int age;

    Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    //默认的是先根据年龄排序的,年龄相同再按照姓名排序
    public int compareTo(Person s){
        int num=new Integer(this.age).compareTo(new Integer(s.age));
        if(num==0){
            return this.name.compareTo(s.name);
        }
        else{
            return num;
        }
    }
    //为了去除重复必须重新构造hashCOde
    public int hashCode()
    {
        return name.hasCode()+age*37;
    }

    //当哈希值相同的时候才会执行
    public boolean equals(Object obj){
        if(!(obj instanceof Person)){
            throw new ClassCastException("类型不匹配");
        }
        Person p=(Person)obj;
        return this.name.equals(p.name) && this.age==p.age;
    }
    public String toString(){
        return "姓名:"+name+"年龄:"+age;
    }
}

如果不更改Person对象的源码,就是按照默认的排序规则(先按照年龄再根据姓名),好在TreeMap

class PersonNameComparator implements Comparator<Person>{
    public int compare(Person s,Person s2){
        int re=s.getName().compareTo(s2.getName());
        if(re==0){
            return new Integer(s.getAge()).compareTo(new Integer(s2.getAge()));
        }
        return re;
    }
}

测试类

public static void main(String[] args){
    TreeMap<Person,String> tm=new TreeMap<Person,String>(new PersonNameComparator());
    tm.put(new Person("azhang3",18),"beijing");
    tm.put(new Person("dzhang4",19),"didu");
    tm.put(new Person("bzhang5",21),"modu");

    Set<Map.Entry<Person,String>> entrySet=map.entrySet();
    Iterator<Map.Entry<Person,String>> iter=entrySet.iterator();//得到Set集合的迭代器
    while(iter.hasNext()){
        Map.Entry<Person,String> pa=iter.next();//通过迭代器获取键
        Person key=pa.getKey();//获取键
        String value=pa.getValue();
        System.out.println(key.toString()+":"+value);
    }
}

2 获取指定字符串中的字母次数,如“asdfsafddwewdwss”,打印结果a(1)d(4)……

public String charCount(String str){
    chars[] chs=str.toCharArray();
    TreeMap<Character,Integer> tm=new TreeMap<Character,Integer>();//错误的,泛型不允许使用基本类型必须使用引用类型TreeMap<char,int> tm=new TreeMap<char,int>();
    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;
    }
    StringBuilder sb=new StringBuilder();
    Set<Map.Entry<Character,Integer>> enteySet=tm.entrySet();
    Iterator<Map.Entry<Character,Integer>> it=enteySet.iterator();
    while(it.hasNext()){
        Map.Entry<Character,Integer> me=it.next();
        Character ch=me.getKey();
        Integer value=me.getValue();
        sb.append(ch+"("+value+")");
    }
    return sb.toString();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CrazyMo_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值