黑马程序员_Java基础_集合框架(三)_16
来源:互联网 发布:python 脚本版本 编辑:程序博客网 时间:2024/04/19 03:16
------- android培训、java培训、期待与您交流!----------
导读:Map概述,Map子类对象的特点,Map共性的方法,Map-Keyset,Map练习,TreeMap练习,Map集合扩展
1、集合Map概述、Map子类对象的特点、Map共性的方法
l Map和Collection都属于集合框架中的顶层接口,他们两个之间没有外观的必然联系。Map是最顶层的接口,它中的方法是最共性的方法。因此要了解。
l java.util接口Map<K,V>,有两个这个是最关键的,K代表Key,V代表Value的意思。在使用的时候要同时往里面扔两个元素。他们之间有映射关系。将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
l 键值对的方式,应用的最多了。它不仅仅是给我元素加索引了,它给我元素起名字都行。名字用字符串表示,字符串是对象。
l Collection是单列集合,Map是双列集合(键值对存的是引用)。
l Map集合:该集合存储键值对。一对一对往里存。而且要保证键的唯一性。
1,添加。
Ø put(K key, V value) //它的存是通过put来完成的。返回值是一个V。而HashSet的add()返回的是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:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。jdk1.0.效率低。(为了成功地在哈希表中存储和获取对象,用作键的对象必须实现 hashCode 方法和 equals 方法。)
|--HashMap:底层是哈希表数据结构,允许使用 null 值和 null 键,该集合是不同步的。将hashtable替代,jdk1.2.效率高。
|--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。
l 发现Map和Set很像。其实,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=zhangsan1,03=zhangsan3)
}
}
2、集合(Map-Keyset)
l 以前的取出都是迭代器,Map方法中没有迭代器。如果果能拿到所有的键的话,是不是可以拿到所有的值。
l map集合的两种取出方式:
1,Set<k>keySet:将map中所有的键存入到Set集合。因为set具备迭代器。
所有可以迭代方式取出所有的键,在根据get方法。获取每一个键对应的值。
Map集合的取出原理:将map集合转成set集合。在通过迭代器取出。(Map集合本不需要迭代器)
2,Set<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集合的get(Key)方法获取键对应的值。
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"); //我们做了hashCode和eqauls的复写,所以它以为上面的两个是同一个人,键是同一个键,后面的覆盖前面的。
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)覆盖两个方法。
4、TreeMap练习
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);
}
}
}
5、TreeMap练习-字母出现的次数
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>();
//不能往这里面存char和int,只能传入引用类型,否则会出现错误
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();
}
}
6、Map集合的扩展(map扩展知识)
l 大的集合中嵌套着小的集合。原来是一一映射,现在是一对于多的映射
l map集合被使用是因为具备映射关系。
第一种方式:
"jiuyeban" "01" "wangwu";
"jiuyeban" "02""zhaoliu";
第二种方式:
"yureban" Student("01" "zhangsan"); //实际开发中一般是把学生的学号和姓名封装成一个对象。用一个映射,而不是嵌套映射来存。这个时候内层的就不用Map了,而用Collection集合(List、Set不用保证唯一的话,可以用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培训、期待与您交流!----------
- 黑马程序员_Java基础_集合框架(三)_16
- 黑马程序员_Java基础_集合框架
- 黑马程序员_Java基础_集合框架
- 黑马程序员_java基础_集合框架
- 黑马程序员_Java基础_集合框架(二)_15
- 黑马程序员_Java基础_集合框架(四)_17
- 黑马程序员_Java基础_集合框架1
- 黑马程序员_Java基础_集合框架2
- 黑马程序员_Java基础_集合框架(一)_14
- 黑马程序员_Java基础04_集合框架
- 黑马程序员_Java基础_集合框架成员Collection
- 黑马程序员_Java基础_集合框架成员Map
- 黑马程序员_Java基础_集合框架工具类
- 黑马程序员_Java基础_集合框架1
- 黑马程序员_Java基础_集合框架2
- 黑马程序员_java基础学习笔记06_集合框架
- 黑马程序员_java基础_泛型、集合框架工具类
- 黑马程序员_学习笔记_Java基础_集合(三)
- 使用tcpdump和wireshark对android手机进行网络抓包分析
- 没有方向,不叫发展 No Directions, No Development
- java调用c/c++代码
- iOS 4的无线部署(Xcode3.2 及 Xcode4.2 图文解说)
- kettel的stream lookup报错
- 黑马程序员_Java基础_集合框架(三)_16
- 常用的返回JSON的接口
- Vladimir's Forex Signals & Mentoring
- 日常可能用到的sql
- OPENCV--图像平滑变换(高斯)
- 调试驱动程序的入口
- hadoop安全机制Kerberos详细介绍
- HTTP协议探索之Content-Type(MIME)
- DB2之通过命令导入csv文件数据