Java基础——集合(下)之Map

来源:互联网 发布:打造最好的网络电玩城 编辑:程序博客网 时间:2024/05/23 01:28


个人小结:本篇主要介绍Map集合和泛型。Map 集合类用于存储元素对(称作“键”和“值”),其中每个键映射到一个值。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。具体有泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。
一、Map集合
Map集合: 该集合存储键值对,一对一对往里存,而且要保证键的唯一性。
常用方法:
1、添加
put(K key, V value)
putAll(Map<? extends K,? extends V> m)
2、删除
clear()
remove(Object key)
3、判断
containsKey(Object key)
containsValue(Object value)
isEmpty() 
4、获取
get(Object key)
size()
values()
entrySet() 
keySet()
常用的实现类:
Map--
|--Hashtable :底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。jkd 1.0,效率低
|--HashMap:底层是哈希表数据结构,可以存入null键null值,该集合是不同步的。jdk 1.2,效率高。
|--TreeMap:底层是二叉树数据结构,线程不同步,可以用于给map集合中的键进行排序。
和Set很像,其实,Set集合底层就是使用了Map集合。
示例:
import java.util.*;class MapDemo{public static void main(String[] args) {Map<String,String> map = new HashMap<String,String>();//添加元素,如果添加时出现相同的键,那么后添加的值会覆盖并返回原有键对应的值,System.out.println("put:"+map.put("01","zhangsan1"));System.out.println("put:"+map.put("01","wangwu1"));map.put("02","zhangsan2");map.put("03","zhangsan3");map.put(null,"haha"); //若是 Hashtable 存null,则抛出NullPointerExceptionSystem.out.println("containsKey:"+map.containsKey("02"));//System.out.println("remove:"+map.remove("02"));System.out.println("get:"+map.get("02"));System.out.println("get:"+map.get(null));//可以通过get方法的返回值来判断一个键是否存在。通过返回null来判断。//获取map集合中所有的值。Collection <String> coll = map.values();System.out.println(coll);System.out.println("map:"+map);}}

二、Map集合的两种取出方式

1、Set<K> keySet :  将Map中所有的键存入到Set集合,因为Set具备迭代器。所以可以用迭代方式取出所有的键,再根据get方法,获取每一个键对应的值。 Map集合的取出原理:将Map集合转换成Set集合,在通过迭代器取出。
2、Set<Map.Entry<k,v>> entrySet:  将Map集合中的映射关系存入到了Set集合中,而这个关系的数据类型就是:Map.Entry
示例:
import java.util.*;class MapDemo2 {public static 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();String key = me.getKey();String value = me.getValue();System.out.println(key+":"+value);}/*//先获取map集合的所有键的Set集合,keySet();Set<String> keySet = map.keySet();//有了Set集合,就可以获取其迭代器。Iterator<String> it = keySet.iterator();while (it.hasNext()){String key = it.next();//有了键就可以通过Map集合的get方法获取其对于的值。String value = map.get(key);System.out.println("key:"+key+"...value:"+value);}*/}}/*Map.Entry 其实Entry也是一个接口,他是Map接口中的一个内部接口。*/
练习
/*需求:每一个学生都有对应的归属地,学生Student,地址String.学生属性:姓名,年龄。注意:姓名和年龄相同的视为同一个学生。保证学生的唯一性。步骤:1、描述学生。2、定义map容器,将学生作为键,地址作为值,存入。3,获取map集合中的元素。*/import java.util.*;class MapTest {public static void main(String[] args) {Map<Student,String> map  = new HashMap<Student,String>();map.put(new Student("lisi01",18),"安徽");map.put(new Student("lisi02",19),"广东");map.put(new Student("lisi03",20),"安徽");map.put(new Student("lisi04",23),"广东"); map.put(new Student("lisi04",23),"广西");//第一种取出方式 :KeySetSystem.out.println("*********第一种取出方式 :KeySet*********");Set<Student> keySet = map.keySet();Iterator<Student> it = keySet.iterator();while (it.hasNext()){Student s = it.next();String add = map.get(s); System.out.println(s.getName()+"..."+s.getAge()+"岁,来自"+add);}//第二种取出方式 :EntrySetSystem.out.println("*********第二种取出方式 :EntrySet*********");Set<Map.Entry<Student,String>>  entrySet = map.entrySet();Iterator<Map.Entry<Student,String>> it2 = entrySet.iterator();while (it2.hasNext()){Map.Entry<Student,String> me = it2.next();Student s = me.getKey();String name = s.getName();int age = s.getAge();String add = me.getValue();System.out.println(name+"..."+age+"岁,来自"+add);}}}//定义学生类,并实现Comparable接口class Student implements Comparable<Student>{private String name;private int age;public Student (String name,int age){this.name = name;this.age = age;}//复写compareTo方法public int compareTo(Student s){int num = new Integer(this.age).compareTo(new Integer(s.age));if (num==0)return this.name.compareTo(s.name);return num;}//复写hashCode方法public int hashCode(){return name.hashCode()+age*34;}//复写equals方法public boolean equals(Object obj){if(!(obj instanceof Student))throw new ClassCastException("类型不匹配");Student s = (Student)obj;return this.name.equals(s.name) && this.age==s.age;  }public String getName(){return name;}public int getAge(){return age;}}/*为什么这里用比较器就不行,因为不是 TreeMap !,一般带Tree的才有比较器class Comp implements Comparator<Student>{public int compare(Student s1,Student s2){int num = s1.getName().compareTo(s2.getName());if (num==0)return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));return num;}}*/
练习
/*需求:对学生对象的年龄进行升序排序。因为数据是以键值对形式存在的。所以要使用可以排序的Map集合,TreeMap.*/import java.util.*;class MapTest2 {public static void main(String[] args) {TreeMap<Student,String> tm = new TreeMap<Student,String>(new StuNameComp());tm.put(new Student("tlisi01",34),"安徽");tm.put(new Student("clisi02",19),"广东");tm.put(new Student("blisi03",20),"安徽");tm.put(new Student("hlisi04",23),"广东"); tm.put(new Student("hlisi04",23),"广西");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();Student s = me.getKey();String add = me.getValue();System.out.println(s.getName()+":"+s.getAge()+"岁,来自:"+add);}}}//定义比较器class StuNameComp implements Comparator<Student>{public int compare(Student s1,Student s2){int num = s1.getName().compareTo(s2.getName());if (num==0)return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));return num;}}
练习
/*练习需求:"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{public static void main(String[] args) {String str =  "sdfgz+xcv-asd9fxcvdf";char[] cha = str.toCharArray();TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();for (int x = 0;x<cha.length ; x++){/*自己方法if (!tm.containsKey(cha[x])){tm.put(cha[x],1);}else {int y = tm.get(cha[x]).intValue();y++;tm.put(cha[x],y);}*//*视频方法1Integer value = tm.get(cha[x]);if(value==null){tm.put(cha[x],1);}else{value = value +1;tm.put(cha[x],value);}*///视频方法2if(!(cha[x]>='a' && cha[x]<='z'|| cha[x]>='A' && cha[x]<='Z'))continue;int count = 0;Integer value = tm.get(cha[x]);if (value!=null)count = value;count++;tm.put(cha[x],count);System.out.println(tm);}Set<Map.Entry<Character,Integer>> entrySet = tm.entrySet();Iterator<Map.Entry<Character,Integer>> it = entrySet.iterator();while (it.hasNext()){Map.Entry<Character,Integer> s = it.next();Character key = s.getKey();Integer value = s.getValue();System.out.print(key+"("+value+")");}}/*public static String charCount(String str){char[] cha = str.toArrayChar();}*/}

三、Map扩展
map集合被使用是因为具备映射关系。
"yuereban"  "01"  "zhangsan";
"yureban"  "02"  "lisi";
"jiuyeban"  "01" "wangwu";
"jiuyeban"  "02"  "zhaoliu";
一个学校有多个教室,每个教室都有名称。
第一种方式:嵌套集合,大集合里套小集合,小集合当作大集合的一个元素。
第二种方式: 把后两个信息堪称一个学生对象。
"yureban"  Student("01" , "zhangsan");
示例:
import java.util.*;//第一种方式:嵌套集合class MapDemo3 {public static void main(String[] args) {//System.out.println("Hello World!");HashMap<String,HashMap<String,String>> czbk = new HashMap<String,HashMap<String,String>>();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" , "zhangsan");yure.put("02" , "lisi");jiuye.put("01" , "wangwu");jiuye.put("02" , "zhaoliu");jiuye.put("03" , "zhengqi");Set<String> keySet = czbk.keySet();Iterator<String> it = keySet.iterator();while (it.hasNext()){String jiaoshi = it.next();HashMap<String,String> hm = czbk.get(jiaoshi);System.out.println(jiaoshi);getAllInfo(hm);}}public static void getAllInfo(HashMap<String,String> hm){Set<String> keySet = hm.keySet();Iterator<String> it = keySet.iterator();while (it.hasNext()){String id = it.next();String name = hm.get(id);System.out.println(id+":"+name);}}}//第二种方式:封装学生类class MapDemo3 {public static void main(String[] args){HashMap<String,List<Student>> czbk = new HashMap<String,List<Student>>();List<Student> yure = new ArrayList<Student>();List<Student> jiuye = new ArrayList<Student>();czbk.put("yureban",yure);czbk.put("jiuyeban",jiuye);yure.add(new Student("01","zhangsan"));yure.add(new Student("02","lisi"));yure.add(new Student("03","lisi2"));jiuye.add(new Student("01" , "wangwu"));jiuye.add(new Student("02" , "zhaoliu"));jiuye.add(new Student("03" , "zhengqi"));Set<String> keySet = czbk.keySet();Iterator<String> it = keySet.iterator();while (it.hasNext()){String jiaoshi = it.next();List<Student> li = czbk.get(jiaoshi);System.out.println(jiaoshi);getAllInfo(li);}}public static void getAllInfo(List<Student> li){Iterator<Student> it = li.iterator();while (it.hasNext()){Student stu = it.next();System.out.println(stu.toString());}}}class Student{private String id;private String name;public Student(String id,String name){this.id = id;this.name = name;}public String toString(){return id+":"+name;}}

四、泛型

泛型:jdk1.5版本后出现的新特性,用于解决安全问题,是一个类型安全机制。
好处:
1、将运行时出现的问题ClassCastException,转移到了编译时期,方便于程序员解决问题,让运行时期问题减少,安全。
2、避免了强制转换的麻烦。
泛型格式:通过<>来定义要操作的引用数据类型。
在使用java提供的对象时,什么时候写泛型呢?
通常在集合框架中很常见。只要见到<>就要定义泛型。其实<>就是用来接收类型的。
当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。
示例:

class Worker{}class Student{}/*class Tool{private Worker w;public void setWorker(Worker w){this.w= w;}public Worker getWorker(){return w;}}*///泛型前做法class Tool{private Object obj;public void setObject(Object obj){this.obj= obj;}public Object getObject(){return obj;}}//泛型类/*什么时候定义泛型类?当类中要操作的引用数据类型不确定的时候,早期定义Object来完成扩展,现在定义泛型来完成扩展。*/class Utils<QQ>{privateQQ q;public void setObject(QQ q){this.q = q;}public QQ getObject(){return q;}}class  GenericDemo3{public static void main(String[] args) {/*Tool t = new Tool();t.setObject(new Student());Worker w = (Worker)t.getObject();*/Utils<Worker> u = new Utils<Worker>();u.setObject(new Student());Worker w = u.getObject();}}
示例:
/*class Demo<T>{public void show(T t){System.out.println("show:"+t);}public void print(T t){System.out.println("print:"+t);}}*//*泛型类定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义在方法上。*//*特殊之处:静态方法不可以访问类上定义的泛型。如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法上。*/class Demo<T> {public void show(T t){System.out.println("show:"+t);}public <Q> void print(Q q){System.out.println("print:"+q);}public static <S> void method(S s){System.out.println("method:"+s);}}class  GenericDemo4{public static void main(String[] args) {/*Demo<Integer> d = new Demo<Integer>();d.show(new Integer(4));//d.print("haha");Demo<String> d1 = new Demo<String>();d1.print("haha");//d1.show(5);*//*Demo d = new Demo();d.show("haha");d.show(new Integer(4));d.print(5);*/Demo<String> d = new Demo<String>();d.show("haha");//d.show(4);d.print(5);d.print("hehe");d.method("hhahahahah");}}

五、泛型的限定
? 通配符,也可以理解为占位符
? extends E;可以接收E类型或者E的子类型。————上限
如:ArrayList<? extends Number>x = new ArrayList<Integer>();
? super E:可以接收E类型或者E的父类型,—————下限
 如:ArrayList<? super Integer>x = new ArrayList<Number>();
示例:
import java.util.*;class  GenericDemo6{public static void main(String[] args) {/*ArrayList<String> al = new ArrayList<String>();al.add("abc1");al.add("abc2");al.add("abc3");ArrayList<Integer> al1 = new ArrayList<Integer>();al1.add(4);al1.add(7);al1.add(1);printColl(al);printColl(al1);*/ArrayList<Person> al = new ArrayList<Person>();al.add(new Person("abc1"));al.add(new Person("abc2"));al.add(new Person("abc3"));//printColl(al);ArrayList<Student> al1 = new ArrayList<Student>();al1.add(new Student("abc1"));al1.add(new Student("abc8"));al1.add(new Student("abc9"));printColl(al1); //ArrayLis<Person> al = new ArrayList<Student>(); --error!}public static void printColl(ArrayList<? extends Person> al){Iterator<? extends Person> it = al.iterator();while (it.hasNext()){System.out.println(it.next().getName());}}/*public static void printColl(ArrayList<?>/*<String> al)//ArrayList<String> al = new ArrayList<Integer>();  ---error!{Iterator<?>/*<String>it = al.iterator();while (it.hasNext()){System.out.println(it.next());} }*/}class Person{private String name;Person(String name){this.name = name;}public String getName(){return name;}}class Student extends Person{Student(String name){super(name);}}class Student implements Comparable<Student>//<? super E>{public int compareTo()(Student s){this.getName();}}class Comp implements Comparator<Person>{public int compare(Person s1,Person s2){Person s1 = new Student("abcd1");return s1.getName().compareTo(s2.getName());}}/*TreeSet<Student> ts = new TreeSet<Student>(new Comp());ts.add(new Student("abcd1"));ts.add(new Student("abcd1"));ts.add(new Student("abcd1"));*/



0 0
原创粉丝点击