黑马程序员——Java要点笔记——集合框架(Map)

来源:互联网 发布:锤子便签mac版 编辑:程序博客网 时间:2024/05/20 06:09

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

Map派系

day18 01-常用对象API(集合框架-Map集合特点&常用方法)

1、Map在集合框架中的位置

2、Map与Collection同级,为顶层接口。Map集合的使用频率相当高。接口Map<K,V>

3、Map集合与Collection集合的区别

    ①Map集合一次添加一对元素。Collection集合一次添加一个元素。

    ②Map也称为双列集合。Collection集合也称为单列集合

       其实Map集合中存储的就是键值对。K——Key(键),V——Value(值)。Map集合中必须保证键的唯一性!

4、Map接口常用方法,Map集合可以根据键来操作

    (1)增

       value  put(key , value):返回前一个和key关联的值。如果没有,返回null。(可以理解为同时具备add和set的功能)

    (2)删

       void  clear():清空map集合

       value  remove(key):根据指定的key删除这个键值对(不是单独删除键,是删除整个键值对)

    (3)查

       (3.1)判断

           boolean containKey(key)

           boolean containValue(value)

           boolean  isEmpty()

       (3.2)获取

           value get(key):通过键获取值,如果没有该键返回null。当然可以通过返回null,来判断是否包含指定键。

           int  size():获取键值对的个数。

day18 02-常用对象API(集合框架-Map集合-常用方法演示)

1、增,代码示例:

publicclass Demo38 {    public staticvoid main(String args[]){       Map<Integer,String>map = newHashMap<Integer,String>();       System.out.println(map.put(4,"张三"));       System.out.println(map.put(4,"李四"));    }}

运行结果:null

张三

{4=李四}

2、不要忘记,value  put(key , value):返回前一个和key关联的值。如果没有,返回null。(可以理解为同时具备add和set的功能)

3、键相同,值会覆盖。

4、删,代码示例:

publicclass Demo38 {    public staticvoid main(String args[]){       Map<Integer,String>map = newHashMap<Integer,String>();       map.put(3,"张三");       map.put(4,"李四");       map.put(5,"王五");       //删除       map.remove(4);       System.out.println(map);    }}

运行结果:{3=张三, 5=王五}

5、查——判断,代码示例:

publicclass Demo38 {    public staticvoid main(String args[]){       Map<Integer,String>map = newHashMap<Integer,String>();       map.put(3,"张三");       map.put(4,"李四");       map.put(5,"王五");       System.out.println(map.containsKey(3));       System.out.println(map.containsValue("王五"));    }}

运行结果:true

true

6、查——获取,代码示例:

publicclass Demo38 {    public staticvoid main(String args[]){       Map<Integer,String>map = new HashMap<Integer,String>();       map.put(3,"张三");       map.put(4,"李四");       map.put(5,"王五");       System.out.println(map.get(3));       System.out.println(map.get(10));    }}

运行结果:张三

null

day18 03-常用对象API(集合框架-遍历Map集合1——keySet)

1、接口Map<K,V>

       Set<K>  keySet()

              返回此映射中所包含的键的Set视图。

2、说白了,就是通过keySet()方法获得该Map集合中所有键的Set集合,再通过Set集合的迭代器拿到每一个键,最后用Map集合中的get(key)方法拿对应的值。Map没迭代器,那就先转化成有迭代器的集合,再用迭代器。

3、代码示例:

publicclass Demo38 {    public staticvoid main(String args[]){       Map<Integer,String>map = newHashMap<Integer,String>();       map.put(3,"张三");       map.put(4,"李四");       map.put(5,"王五");       //通过keySet方法拿到Map集合中所有键的集合       Set<Integer>keySet = map.keySet();       //通过Set集合的迭代器拿每一个键       Iterator<Integer>it = keySet.iterator();       while(it.hasNext()){           //通过get方法拿值           System.out.println(map.get(it.next()));       }    }}

代码示例:李四

张三

王五

4、演示图解

day18 04-常用对象API(集合框架-遍历Map集合2——entrySet)

1、接口Map<K,V>

       public  Set<Map.Entry<K ,V>>  entrySet()

       返回此映射所包含的映射关系的Set视图。(返回的是结婚证,包含着丈夫也包含着妻子)

2、keySet是拿所有的丈夫。entrySet是拿所有的结婚证,有了结婚证,丈夫妻子你都能拿。

3、接口Map.Entry<K,V>

方法摘要

 boolean

equals(Object o)
          比较指定对象与此项的相等性。

 K

getKey()
          返回与此项对应的键。

 V

getValue()
          返回与此项对应的值。

 int

hashCode()
          返回此映射项的哈希码值。

 V

setValue(V value)
          用指定的值替换与此项对应的值(可选操作)。

4、代码示例

publicclass Demo46 {    public staticvoid main(String[] args) {       Map<Integer,String>map = newHashMap<Integer,String>();       map.put(3,"zhangsan");       map.put(4,"lisi");       map.put(5,"wangwu");       Set<Map.Entry<Integer,String>> set = map.entrySet();       Iterator<Map.Entry<Integer,String>> it = set.iterator();       while(it.hasNext()){           Map.Entry<Integer,String> me = it.next();           Integerkey = me.getKey();           Stringvalue = me.getValue();           System.out.println(key+"...."+value);       }    }}

运行结果:3....zhangsan

         4....lisi

         5....wangwu

5、演示图例

6、Map.Entry是Map接口的嵌套类。

       接口Map<K,V>

              嵌套类摘要

                     static  interface Map.Entry<K,V>

                                                 映射项(键-值对)

7、为什么Entry非要定义在Map里面?放外面不行吗?

       Entry是键和值的映射关系对象。因此,你必须先有Map映射。而Entry把关系封装成对象。这个关系在访问Map中的键和值。外部规则里有内部跪着,内部规则可以直接访问外部规则中的内容。内部类(或内部接口)。

day18 05-常用对象API(集合框架-遍历Map集合3——values)

1、接口Map<K,V>

       Collection<V>values()

              返回此映射中包含的值的Collection视图。(即只拿值)

2、为何他不是Set而是Collection?因为Key是唯一的,但value不一定唯一。

3、代码示例:

publicclass Demo46 {    public staticvoid main(String[] args) {       Map<Integer,String>map = newHashMap<Integer,String>();       map.put(3,"zhangsan");       map.put(4,"lisi");       map.put(5,"wangwu");       Collection<String>co = map.values();       Iterator<String>it = co.iterator();       while(it.hasNext()){           System.out.println(it.next());       }    }}

    运行结果:zhangsan

             lisi

             wangwu

4、关于遍历Map集合的3个方式

(1)(返回一个键集合):通过Set<K> keySet(),将Map中的Key返回成一个Set集合。之后利用Set集合的Iterator,和Map集合的get(Key)来拿所有的值。

(2)(返回一个键值对映射集合):通过Set<Map.Entry<K ,V>> entry(),将Map中的键值对映射关系返回成一个Set集合。之后利用Set集合的Iterator,和Map.Entry<K ,V>类中的getKey()和getValue()方法来拿所有的键和值。

(3)(返回一个值集合):通过Collection<V> values(),将Map中的Value返回成一个Collection集合。之后利用Collection的Iterator,来拿所有的值。

day18 06-常用对象API(集合框架-Map集合——常见子类对象)

1、Map接口下常用的子类

              |——HashTable:内部结构是哈希表,是同步的。不允许null作为键,不允许null作为值。

              |——HashMap:内部结构是哈希表,是不同步的。允许null作为键,允许null作为值。

              |——TreeMap:内部结构式二叉树,是不同步的。可以对Map集合中的键进行排序。

2、HashTable下有一个子类——Properties,使用频率相当高。Propertise类表示了一个持久的属性集。用来存储键值对性的配置文件信息。他可以和IO技术相结合。

day18 07-常用对象API(集合框架-Map集合——HashMap存储自定义对象)

1、需求:将学生对象和学生的归属地,通过键和值存储到Map集合中。如果两个Student对象的名字和年龄相同,则认为是同一个人。

2、代码示例一:该代码有问题

classStudent {    private String name;    private intage;    public Student(String name,int age){       this.name= name;       this.age= age;    }    public voidsetName(String name){       this.name= name;    }    public voidsetAge(int age){       this.age= age;    }    public String getName(){       return name;    }    public intgetAge(){       return age;    }    public String toString(){       return "name:"+name+"...age"+age;    }}publicclass AWTDemo05 {    public staticvoid main(String[] args) {       HashMap<Student,String>hm = newHashMap<Student,String>();       hm.put(new Student("lisi",38),"beijing");       hm.put(new Student("zhaoliu",24),"dalian");       hm.put(new Student("wangwu",24),"shenyang");       hm.put(new Student("lisi",38),"shanghai");       Set<Student>set = hm.keySet();       Iterator<Student>it = set.iterator();       while(it.hasNext()){           Students = it.next();           System.out.println(s+"——"+hm.get(s));       }    }}

运行结果:name:lisi...age38——beijing

         name:wangwu...age24——shenyang

         name:zhaoliu...age24——dalian

         name:lisi...age38——shanghai

可以发现,lisi并没有被视为是同一个人。因为还没有覆盖Student类中的hashCode()方法和equals()方法。

3、代码示例二:此代码仍然有问题

classStudent {    private String name;    private intage;    public Student(String name,int age){       this.name= name;       this.age= age;    }    public voidsetName(String name){       this.name= name;    }    public voidsetAge(int age){       this.age= age;    }    public String getName(){       return name;    }    public intgetAge(){       return age;    }    public String toString(){       return "name:"+name+"...age"+age;    }    public inthashCode(){       return name.hashCode()+age;    }}publicclass AWTDemo05 {    public staticvoid main(String[] args) {       HashMap<Student,String>hm = newHashMap<Student,String>();       hm.put(new Student("lisi",38),"beijing");       hm.put(new Student("zhaoliu",24),"dalian");       hm.put(new Student("wangwu",24),"shenyang");       hm.put(new Student("lisi",38),"shanghai");       Set<Student>set = hm.keySet();       Iterator<Student>it = set.iterator();       while(it.hasNext()){           Students = it.next();           System.out.println(s+"——"+hm.get(s));       }    }}

运行结果:name:wangwu...age24——shenyang

         name:zhaoliu...age24——dalian

         name:lisi...age38——shanghai

         name:lisi...age38——beijing

可以发现lisi仍然没有被视为是同一个人。因为Student中的hashCode()方法,是name.hashCode()+age;所以两个lisi算出的哈希值仍然相同。之后通过Student类中的equals()方法(这里也就是Object类中的equals()方法),比较是不同的地址值。所以仍被认为是不同的键。

4、代码示例三:该代码是正确的

classStudent {    private String name;    private intage;    public Student(String name,int age){       this.name= name;       this.age =age;    }    public voidsetName(String name){       this.name= name;    }    public voidsetAge(int age){       this.age =age;    }    public String getName(){       return name;    }    public intgetAge(){       return age;    }    public String toString(){       return "name:"+name+"...age"+age;    }    public inthashCode(){       return name.hashCode()+age;    }    public booleanequals(Object obj){       Students = (Student)obj;       return this.name.equals(s.name)&&(this.age==s.age);    }}publicclass AWTDemo05 {    public staticvoid main(String[] args) {       HashMap<Student,String> hm = new HashMap<Student,String>();       hm.put(new Student("lisi",38),"beijing");       hm.put(new Student("zhaoliu",24),"dalian");       hm.put(new Student("wangwu",24),"shenyang");       hm.put(new Student("lisi",38),"shanghai");       Set<Student>set = hm.keySet();       Iterator<Student>it = set.iterator();       while(it.hasNext()){           Students = it.next();           System.out.println(s+"——"+hm.get(s));       }    }}

运行结果:name:wangwu...age24——shenyang

         name:zhaoliu...age24——dalian

         name:lisi...age38——shanghai

    哦了!!!事实证明,HashMap保证键的唯一性,用的也是先hashCode方法再equals方法。

day18 08-常用对象API(集合框架-Map集合——TreeMap存储自定义对象)

1、需求一:利用Student的自然排序,按照年龄从小到大,将Map集合中的Student对象元素进行排序。

2、代码示例:

classStudent implementsComparable{    private String name;    private intage;    public Student(String name,int age){       this.name= name;       this.age= age;    }    public voidsetName(String name){       this.name= name;    }    public voidsetAge(int age){       this.age= age;    }    public String getName(){       return name;    }    public intgetAge(){       return age;    }    public String toString(){       return "name:"+name+"...age"+age;    }    public intcompareTo(Object obj){       Students = (Student)obj;       return this.age-s.age;    }}publicclass AWTDemo06 {    public staticvoid main(String[] args) {       TreeMap<Student,String>tm = newTreeMap<Student,String>();       tm.put(new Student("lisi",38),"beijing");       tm.put(new Student("zhaoliu",24),"dalian");       tm.put(new Student("wangwu",55),"shenyang");       tm.put(new Student("zhangsan",38),"shanghai");       Set<Map.Entry<Student,String>>set = tm.entrySet();       Iterator<Map.Entry<Student,String>>it = set.iterator();       while(it.hasNext()){           Map.Entry<Student,String> me = it.next();           Students = me.getKey();           Stringstr = me.getValue();           System.out.println(s+"..."+str);       }    }}

运行结果:name:zhaoliu...age24...dalian

         name:lisi...age38...shanghai

         name:wangwu...age55...shenyang

    由于zhangsan和lisi年龄都是38岁,所以利用compareTo方法一比,返回值为0.则认为是重复的键。只保留前一个键。且值shanghai覆盖了原来的值beijing。

3、需求二:利用比较器,按照name的字母顺序,将Map集合中的Student对象元素进行排序。

4、代码示例:

classStudent implementsComparable{    private String name;    private intage;    public Student(String name,int age){       this.name= name;       this.age= age;    }    public voidsetName(String name){       this.name= name;    }    public voidsetAge(int age){       this.age= age;    }    public String getName(){       return name;    }    public intgetAge(){       return age;    }    public String toString(){       return "name:"+name+"...age"+age;    }    public intcompareTo(Object obj){       Students = (Student)obj;       return this.age-s.age;    }}classCompartorByName implementsComparator{    public intcompare(Object obj1,Object obj2){       Students1 = (Student)obj1;       Students2 = (Student)obj2;       return s1.getName().compareTo(s2.getName());    }}publicclass AWTDemo06 {    public staticvoid main(String[] args) {       TreeMap<Student,String>tm = newTreeMap<Student,String>(newCompartorByName());       tm.put(new Student("lisi",38),"beijing");       tm.put(new Student("zhaoliu",24),"dalian");       tm.put(new Student("wangwu",55),"shenyang");       tm.put(new Student("lisi",66),"shanghai");       Set<Map.Entry<Student,String>>set = tm.entrySet();       Iterator<Map.Entry<Student,String>>it = set.iterator();       while(it.hasNext()){           Map.Entry<Student,String> me = it.next();           Students = me.getKey();           Stringstr = me.getValue();           System.out.println(s+"..."+str);       }    }}

运行结果:name:lisi...age38...shanghai

         name:wangwu...age55...shenyang

         name:zhaoliu...age24...dalian

由于有两个lisi,所以后面进来而被认为是重复的键。只保留之前的键。但值shanghai覆盖了原来的值beijing。

day18 09-常用对象API(集合框架-Map集合——LinkedHashMap)

1、LinkedHashMap,在保证键唯一的情况下,还可以保证键的有序性。(类似于LinkedHashSet集合)

2、代码示例:

publicclass AwtDemo07 {    public staticvoid main(String[] args) {       LinkedHashMap<Integer,String>lhm = newLinkedHashMap<Integer,String>();       lhm.put(1,"yi");       lhm.put(2,"er");       lhm.put(3,"san");       lhm.put(1,"yiyiyi");       Set<Integer>set = lhm.keySet();       Iterator<Integer>it = set.iterator();       while(it.hasNext()){           Integeri = it.next();           System.out.println(i+"..."+lhm.get(i));       }    }}

    运行结果:1...yiyiyi

             2...er

             3...san

    键相同,后面的值yiyiyi盖掉了原来的值yi。

day18 10-常用对象API(集合框架-Map集合练习——记录字母次数思路)

1、练习:"fdgavcbsacdfs",获取该字符串中每一个字符出现的次数。要求的打印结果是:

a(2)b(1)……

2、分析:很多人的想法是一个个遍历,再计数。但是我嫌麻烦。我发现,一个字母对应一个次数,如a(2)、b(1)。这之间有映射关系。既然如此,我们想到了数组。但数组中有映射的一方是有序编号。如果映射双方是无序的时候,这时就不能想数组了,想到Map集合。又发现,可以保证唯一性的一方具备着顺序,如a、b、c……因此可以使用TreeMap集合。

3、思路:

       这个集合中最终应该存储的是字母和次数的对应关系。

       (1)因为操作的是字符串中的字母,所以先将字符串变成字符数组。

       (2)遍历字符数组,用每个字母作为键,去查Map集合这个表。

                     如果该字母键不存在,就将该字母作为键,1作为值存储到Map集合中。

                     如果该字母键存在,九江该字母键的对应值取出并+1。再将该字母和+1后的值存储到Map集合中。

                     键相同,值覆盖。这样就记录了该字母的出现次数。

       (3)遍历结束,map集合就记录了所有字母出现的次数。

day18 11-常用对象API(集合框架-Map集合练习——记录字母次数代码)

1、代码示例

publicclass AwtDemo09 {    public staticvoid main(String[] args) {       Stringstr = "fdgavcbsacdfs";       Strings = getCharCount(str);       System.out.println(s);    }    public staticString getCharCount(String str){       //将字符串变成字符数组       char[] chs = str.toCharArray();       //定义map集合       Map<Character,Integer>map = newTreeMap<Character,Integer>();       //遍历字符数组       for(inti=0;i<chs.length;i++){           //将数组中的字母作为键去查map表           Integervalue = map.get(chs[i]);           //判断值是否是null           if(value==null){              map.put(chs[i],1);           }else{              map.put(chs[i],value+1);           }       }       return mapToString(map);    }    private staticString mapToString(Map<Character,Integer> map){       StringBuildersb = new StringBuilder();       Iterator<Character>it = map.keySet().iterator();       while(it.hasNext()){           Characterkey = it.next();           Integervalue= map.get(key);           sb.append(key+"("+value+")");       }       return sb.toString();    }}

       运行结果:a(2)b(1)c(2)d(2)f(2)g(1)s(2)v(1)

2、扩展内容,我字符串里来了许多乱七八糟的东西,比如他成了"fdg+avc bsac-dfs"。我想要别的,只要字母。

    在遍历字符数组的for循环中加一个判断,

    if(!(chs[i]>='a'&&chs[i]<='z'||chs[i]>='A'&&chs[i]<='z')){

       continue;

    }

    搞定。

day18 12-常用对象API(集合框架-Map集合练习——Map查表法)

1、Map在有映射关系时,可以优先考虑。其在查表法中的应用较为多见。

2、输入数字,之后星期几的程序

 

   //原来的数组写法    public staticString getWeek(intweek){       if(week<1||week>7){           throw newRuntimeException("没有对应的兴起,请您重新输入");       }       String[]weeks = {"","星期一","星期二","星期三","星期四","星期五","星期六","星期日"};       return weeks[week];    }    //Map写法    public staticString getWeekByMap(String week){       Map<Integer,String>map = new HashMap<Integer,String>();       map.put(1,"星期一");       map.put(2,"星期二");       map.put(3,"星期三");       map.put(4,"星期四");       map.put(5,"星期五");       map.put(6,"星期六");       map.put(7,"星期日");       return map.get(week);    }

3、另外提醒,Map中的值可以是一个集合。因为集合也是对象。


0 0