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


个人小结:本篇主要介绍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,则抛出NullPointerException
		
		System.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),"广西");

		//第一种取出方式 :KeySet
		System.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);
		}
		//第二种取出方式 :EntrySet
		System.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);
			}
			*/

			/*视频方法1
			Integer value = tm.get(cha[x]);

			if(value==null)
			{
				tm.put(cha[x],1);
			}
			else
			{
				value = value +1;
				tm.put(cha[x],value);
			}
			*/
			//视频方法2

			if(!(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>
{
	private	QQ 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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值