黑马程序员_Java基础_集合框架(三)_16

来源:互联网 发布:python 脚本版本 编辑:程序博客网 时间:2024/04/19 03:16

                                            ------- android培训java培训、期待与您交流!----------
 

导读:Map概述,Map子类对象的特点,Map共性的方法,Map-KeysetMap练习,TreeMap练习,Map集合扩展
 

1、集合Map概述、Map子类对象的特点、Map共性的方法

l  MapCollection都属于集合框架中的顶层接口,他们两个之间没有外观的必然联系。Map是最顶层的接口,它中的方法是最共性的方法。因此要了解。

l  java.util接口Map<K,V>,有两个这个是最关键的,K代表KeyV代表Value的意思。在使用的时候要同时往里面扔两个元素。他们之间有映射关系。将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。

l  键值对的方式,应用的最多了。它不仅仅是给我元素加索引了,它给我元素起名字都行。名字用字符串表示,字符串是对象。

l  Collection是单列集合,Map是双列集合(键值对存的是引用)。

l  Map集合:该集合存储键值对。一对一对往里存。而且要保证键的唯一性。

       1,添加。

Ø  put(K key, V value) //它的存是通过put来完成的。返回值是一个V。而HashSetadd()返回的是boolean

Ø  putAll(Map<? extends K,? extends V>m) 添加一大片。

       2,删除。

Ø  clear() //删除所有

Ø  remove(Object key) //根据键来删,因为键唯一

       3,判断。

Ø  containsValue(Object value) //返回boolean

Ø  containsKey(Object key) //返回boolean

Ø  isEmpty()

       4,获取。

Ø  get(Object key)

Ø  size()  //获取长度

Ø  values() //把所有的值拿出来,它返回的是一个集合Collection<V>

 

Ø  entrySet()

Ø  keySet()

l  Map

 |--Hashtable:底层是哈希表数据结构,不可以存入nullnull值。该集合是线程同步的。jdk1.0.效率低。(为了成功地在哈希表中存储和获取对象,用作键的对象必须实现 hashCode 方法和 equals 方法。)

 |--HashMap:底层是哈希表数据结构,允许使用 null 值和 null 键,该集合是不同步的。将hashtable替代,jdk1.2.效率高。

 |--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。

l  发现MapSet很像。其实,Set底层就是使用了Map集合。

l  import java.util.*;

class MapDemo

{

       publicstatic void main(String[] args)

       {

              Map<String,String>map = new HashMap<String,String>();

              //添加元素,添加元素,如果出现添加时,相同的键。那么后添加的值会覆盖原有键对应值。

              //put方法会返回被覆盖的值。

              System.out.println("put:"+map.put("01","zhangsan1"));

              System.out.println("put:"+map.put("01","wnagwu"));//当键相同的话,新的值,替换了老的值。而put会将键原来的对应的原来的值返回来。当第一次存的时候,里面没有值会返回null

              map.put("02","zhangsan2");

              map.put("03","zhangsan3");

              System.out.println("containsKey:"+map.containsKey("022"));//结果为true

              //System.out.println("remove:"+map.remove("02"));  //它会找这个键,将这个键封掉以后,会返回这个键对应的值。

              System.out.println("get:"+map.get("023")); //没有023这个元素,返回结果为null

              map.put("04",null);     //HashMap集合null是可以做为键值来存在的。但是意义不大。

              System.out.println("get:"+map.get("04"));

              //可以通过get方法的返回值来判断一个键是否存在。通过返回null来判断。

              //获取map集合中所有的值。

              Collection<String>coll = map.values();

              System.out.println(coll);

              System.out.println(map);  //返回的结果类似为:(01=zhangsan103=zhangsan3

       }

}

 

2、集合(Map-Keyset

l  以前的取出都是迭代器,Map方法中没有迭代器。如果果能拿到所有的键的话,是不是可以拿到所有的值。

l  map集合的两种取出方式:

1Set<k>keySet:将map中所有的键存入到Set集合。因为set具备迭代器。

       所有可以迭代方式取出所有的键,在根据get方法。获取每一个键对应的值。

       Map集合的取出原理:将map集合转成set集合。在通过迭代器取出。(Map集合本不需要迭代器)

2Set<Map.Entry<k,v>>entrySet:将map集合中的映射关系存入到了set集合中,

       而这个关系的数据类型就是:Map.Entry(用来表示映射关系这种数据类型)

Entry其实就是Map中的一个static内部接口。

为什么要定义在内部呢?

因为只有有了Map集合,有了键值对,才会有键值的映射关系。

关系属于Map集合中的一个内部事物。

而且该事物在直接访问Map集合中的元素。

l  java.util中的接口Map.Entry<K,V>,它中有很多方法,这些方法,在Map的子类集合内部实现的(和迭代器一样)。通过entrySet()方法,可以返回一个实例对象,并存到集合当中去。entrySet()map集合中的映射关系取出。这个关系就是Map.Entry类型。通过迭代,返回的是一个关系,在这个关系中即有对象也有值,所以它里面封装的方法,getKey()getValue()可以取到里面的键和值。可以将些理解为结婚证书,把结婚证书取出来后,里面写的有丈夫和妻子的名字,丈夫和妻子的关系是结婚证书的话,那么这个类型即不是丈夫类型,也不是妻子类型。又单独定义了一种类型,叫Map.Entry

l  import java.util.*;

class MapDemo2

{

       publicstatic void main(String[] args)

       {

              Map<String,String>map = new HashMap<String,String>();

              map.put("02","zhangsan2");

              map.put("03","zhangsan3");

              map.put("01","zhangsan1");

              map.put("04","zhangsan4");

              //Map集合中的映射关系取出。存入到Set集合中。

              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();

                     Stringkey = me.getKey();

                     String value = me.getValue();

                     System.out.println(key+":"+value);

              }

              /*

              //先获取map集合的所有键的Set集合,keySet();

              Set<String>keySet = map.keySet(); //Set集合也带泛型,String是键的类型

              //有了Set集合。就可以获取其迭代器。用迭代器,取出Set集合中的键

              Iterator<String>it = keySet.iterator();

              while(it.hasNext())

              {

                     Stringkey = it.next();

                     //有了键可以通过map集合的getKey)方法获取键对应的值。

                     Stringvalue  = map.get(key);

                     System.out.println("key:"+key+",value:"+value);

              }

              */

       }

}

/*

Map.Entry 其实Entry也是一个接口,它是Map接口中的一个内部接口。

interface Map

{

       publicstatic interface Entry

       {

              publicabstract Object getKey();

              publicabstract Object getValue();

       }

}

class HashMap implements Map //HashMap实现的是Map接口,那Map.Entry是怎样实现的呢?

{

       classHahs implements Map.Entry //使用内部类

       {

              public  Object getKey(){}

              public  Object getValue(){}

       }

}*/

l  //为什么把Entry定义成Map的一个子接口呢?为什么不定义在外面呢?

Entry代表映射关系,你是不是先有Map集合,才有映射关系,那么这个关系是不是Map集合中的一个内部的事物。所有只有有了Map集合才能有关系。而且这个关系是不是在直接访问Map集合中一个元素。所以定义成一个内部规则。(能加Static的接口一定是一个内部的接口public static interfaceMap.Entry<K,V>,接口只有在成员的位置上才能加静态修饰符)

l  Map中有一个静态类摘要:staticinterface Map.Entry<K,V> 映射项(键-值对)。

 

3、集合Map练习

l  每一个学生都有对应的归属地。

学生Student,地址String

学生属性:姓名,年龄。

注意:姓名和年龄相同的视为同一个学生。

保证学生的唯一性。

1,描述学生。

2,定义map容器。将学生作为键,地址作为值。存入。

3,获取map集合中的元素。

import java.util.*;

class Student implementsComparable<Student>

{

       privateString name;

       privateint age;

       Student(Stringname,int age)

       {

              this.name= name;

              this.age= age;

       }

       publicint compareTo(Student s)

       {

              intnum = new Integer(this.age).compareTo(new Integer(s.age));

              if(num==0)

                     returnthis.name.compareTo(s.name);

              returnnum;

       }

       //凡是想到hash就要想到hash表,想到hash表,就要想到hash表的两个方法,一个是hashCode,一个是equals()

       publicint hashCode()

       {

              returnname.hashCode()+age*34;

       }

       publicboolean equals(Object obj) //Object类中的Object方法,不要用泛型。

       {

              if(!(objinstanceof Student))//return false;是可以的但是没有意义,遇到问题抛异常。

                     thrownew ClassCastException("类型不匹配"); //RuntimeException太大了,可以抛出一个更准确的。

              Students = (Student)obj;

              returnthis.name.equals(s.name) && this.age==s.age;

       }

       publicString getName()

       {

              returnname;

       }

       publicint getAge()

       {

              returnage;

       }

       publicString toString()

       {

              returnname+":"+age;

       }

}

class MapTest

{

       publicstatic void main(String[] args)

       {

              HashMap<Student,String>hm = new HashMap<Student,String>();

              hm.put(newStudent("lisi1",21),"beijing");

              hm.put(newStudent("lisi1",21),"tianjin"); //我们做了hashCodeeqauls的复写,所以它以为上面的两个是同一个人,键是同一个键,后面的覆盖前面的。

              hm.put(newStudent("lisi2",22),"shanghai");

              hm.put(newStudent("lisi3",23),"nanjing");

              hm.put(newStudent("lisi4",24),"wuhan");

              //第一种取出方式 keySet

              Set<Student>keySet = hm.keySet();

              Iterator<Student>it = keySet.iterator(); //可以把两句话变成一句话来写:keySet.iterator();

              while(it.hasNext())

              {

                     Studentstu = it.next();

                     Stringaddr = hm.get(stu);

                     System.out.println(stu+".."+addr);

              }

              //第二种取出方式 entrySet

              Set<Map.Entry<Student,String>>entrySet = hm.entrySet();

              Iterator<Map.Entry<Student,String>>iter = entrySet.iterator();

              while(iter.hasNext())

              {

                     Map.Entry<Student,String>me = iter.next();

                     Studentstu = me.getKey();

                     Stringaddr = me.getValue();

                     System.out.println(stu+"........."+addr);

              }

       }

}

l  一个类,如果你认为他产生的对象特别多的话,这个多的对象就有可能,要存储起来,用什么容易存,要看需求而定。有可能用Hash表,有可能用到二叉树,有可能用到数组。你最好让他有一个自然顺序,用的上的话,就用,用不上也无所谓。

l  如果同时要创建多个对象要被用的时候,一定要做这些动作:(1)实现,(2)覆盖两个方法。

 

4TreeMap练习

l  凡是带Tree的都涉及比较器。

l  需求:对学生对象的年龄进行升序排序。

因为数据是以键值对形式存在的。所以要使用可以排序的Map集合。TreeMap

l  import java.util.*;

class StuNameComparator implementsComparator<Student> //自定义一个比较器

{

       publicint compare(Student s1,Student s2)

       {

              intnum = s1.getName().compareTo(s2.getName());

              if(num==0)

                     returnnew Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));

              returnnum;

       }

}

class MapTest2

{

       publicstatic void main(String[] args)

       {

              TreeMap<Student,String>tm = new TreeMap<Student,String>(new StuNameComparator());     //让容器自身有比较性,传进来一个比较器对象

              tm.put(newStudent("blisi3",23),"nanjing");

              tm.put(newStudent("lisi1",21),"beijing");

              tm.put(newStudent("alisi4",24),"wuhan");

              tm.put(newStudent("lisi1",21),"tianjin");

              tm.put(newStudent("lisi2",22),"shanghai");

              Set<Map.Entry<Student,String>>entrySet = tm.entrySet();

              Iterator<Map.Entry<Student,String>>it = entrySet.iterator();

              while(it.hasNext())

              {

                     Map.Entry<Student,String>me = it.next();

                     Studentstu = me.getKey();

                     Stringaddr = me.getValue();

                     System.out.println(stu+":::"+addr);

              }

       }

}

 

5TreeMap练习-字母出现的次数

l  第一次用a字母作为键去找集合。那么集合没有a这个键,所以也没有对应的次数,返回null。如果为null,让就将a字母和1存入集合。如果指定的键已经存在,说明有对应的次数。就将对应的次数取出,并自增后在重新存入集合。

l  练习:

"sdfgzxcvasdfxcvdf"获取该字符串中的字母出现的次数。

希望打印结果:a(1)c(2).....

通过结果发现,每一个字母都有对应的次数。说明字母和次数之间都有映射关系。

注意了,当发现有映射关系时,可以选择map集合。

因为map集合中存放就是映射关系。

什么使用map集合呢?

当数据之间存在这映射关系时,就要先想map集合。

思路:

1,将字符串转换成字符数组。因为要对每一个字母进行操作。

2,定义一个map集合,因为打印结果的字母有顺序,所以使用treemap集合。

3,遍历字符数组。

       将每一个字母作为键去查map集合。

       如果返回null,将该字母和1存入到map集合中。

       如果返回不是null,说明该字母在map集合已经存在并有对应次数。

       那么就获取该次数并进行自增。,然后将该字母和自增后的次数存入到map集合中。覆盖调用原理键所对应的值。

4,将map集合中的数据变成指定的字符串形式返回。

*/

import java.util.*;

class MapTest3

{

       publicstatic void main(String[] args)

       {

              Strings= charCount("ak+abAf1c,dCkaAbc-defa");

              System.out.println(s);

       }

       publicstatic String charCount(String str)

       {

              char[]chs = str.toCharArray();

              TreeMap<Character,Integer>tm = new TreeMap<Character,Integer>();

              //不能往这里面存charint,只能传入引用类型,否则会出现错误

            intcount = 0; //count定义在外面比较好,因为定义在外面不用像定义在里面那样开辟空间,释放空间,开辟空间,释放空间。

              for(intx=0; x<chs.length; x++)

              {

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

                            continue;

                     Integervalue = tm.get(chs[x]);

                     if(value!=null)

                            count= value;

                     count++;

                     tm.put(chs[x],count);//直接往集合中存储字符和数字,为什么可以,因为自动装箱。往里面存的时候,它怎么排的序呢?因为键Character它实现了Comparable接口,有默认的自然排序。

                     count= 0; //每次用完之后要将count清零。

                     /* 

                     if(value==null)  //这种方式还要以用上面的那一种方式代替。

                     {

                            tm.put(chs[x],1);

                     }

                     else

                     {

                            value= value + 1;

                            tm.put(chs[x],value);

                     }

                     */

              }

              StringBuildersb = new StringBuilder();

              Set<Map.Entry<Character,Integer>>entrySet = tm.entrySet();

              Iterator<Map.Entry<Character,Integer>>  it = entrySet.iterator();

              while(it.hasNext())

              {

                     Map.Entry<Character,Integer>me = it.next();

                     Characterch = me.getKey();

                     Integervalue = me.getValue();

                     sb.append(ch+"("+value+")");

              }

              returnsb.toString();

       }

 

}

 

6Map集合的扩展(map扩展知识)

l  大的集合中嵌套着小的集合。原来是一一映射,现在是一对于多的映射

l  map集合被使用是因为具备映射关系。

第一种方式:

"jiuyeban" "01" "wangwu";

"jiuyeban" "02""zhaoliu";

第二种方式:

"yureban"  Student("01" "zhangsan"); //实际开发中一般是把学生的学号和姓名封装成一个对象。用一个映射,而不是嵌套映射来存。这个时候内层的就不用Map了,而用Collection集合(ListSet不用保证唯一的话,可以用List,保证唯一用Set集合),来存储多个student对象

"yureban" Student("02""lisi");

l  一个学校有多个教室。每一个教室都有名称。

import java.util.*;

class Student

{

       privateString id;

       privateString name;

       Student(Stringid,String name)

       {

              this.id= id;

              this.name= name;

       }

       publicString toString()

       {

              returnid+":::"+name;

       }

}

class MapDemo3

{

       publicstatic void demo()

       {

              //第二种方式

              HashMap<String,List<Student>>czbk = new HashMap<String,List<Student>>();

              List<Student>reyu = new ArrayList<Student>();

              List<Student>jiuye = new ArrayList<Student>();

              czbk.put("yureban",reyu);

              czbk.put("jiuyeban",jiuye);

              reyu.add(newStudent("01","zhagnsa"));

              reyu.add(newStudent("04","wangwu"));

              jiuye.add(newStudent("01","zhouqi"));

              jiuye.add(newStudent("02","zhaoli"));

              Iterator<String>it = czbk.keySet().iterator();

              while(it.hasNext())

              {

                     StringroomName = it.next();

                     List<Student>room = czbk.get(roomName);

                     System.out.println(roomName);

                     getInfos(room);

              }

       }

       publicstatic void getInfos(List<Student> list)

       {

              Iterator<Student>it = list.iterator();

              while(it.hasNext())

              {

                     Students = it.next();

                     System.out.println(s);

              }

       }

       publicstatic void main(String[] args)

       {

               demo();

              /*    //第一种方式

              HashMap<String,List<Student>>czbk = new HashMap<String,List<Student>>();

              HashMap<String,String>yure = new HashMap<String,String>();

              HashMap<String,String>jiuye = new HashMap<String,String>();

              czbk.put("yureban",yure);

              czbk.put("jiuyeban",jiuye);

              yure.put("01","zhagnsan");

              yure.put("02","lisi");

              jiuye.put("01","zhaoliu");

              jiuye.put("02","wangwu");

              //遍历czbk集合。获取所有的教室。

              Iterator<String>it = czbk.keySet().iterator();

              while(it.hasNext())

              {

                     StringroomName = it.next();

                     HashMap<String,String>room = czbk.get(roomName);

                    

                     System.out.println(roomName);

                     getStudentInfo(room); //可以将,下面的getStudentInfo的方法代码放在这里,大圈套小圈。一对多的关系。

              }

//            getStudentInfo(jiuye);

//            getStudentInfo(yure);

*/

       }

       publicstatic void getStudentInfo(HashMap<String,String> roomMap)

       {

              Iterator<String> it =roomMap.keySet().iterator();

              while(it.hasNext())

              {

                     Stringid = it.next();

                     Stringname = roomMap.get(id);

                     System.out.println(id+":"+name);

              }

       }

}
 

                                           ------- android培训java培训、期待与您交流!----------  

0 0
原创粉丝点击