天天看点

集合框架(HashSet,HashMap,HashTable)

一,Map集合的基本操作

package fighting;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class MapDemo {

	/**
	 * Map:存储一组成对的键值对象,key不要求有序,但不能重复;value也不要求有序,但允许重复。
	 * 
	 * Collection是单列集合,Map是双列集合。
	 * 
	 * 1,添加
	 *    put(k,v)
	 *    pubAll()
	 * 2,删除
	 *    clear()
	 *    remove(k)
	 * 3,判断
	 *    containsKey()
	 *    containsValue()
	 *    isEmpty()
	 * 4,获取
	 *    get()
	 *    size()
	 *    values()
	 *    
	 *    entrySet()
	 *    keySet()
	 *    
	 * Map
	 *  |-HashTable:底层是哈希表数据结构,不可以存入null键和null值,线程同步,效率低。
	 *              用作键的对象必须实现hashCode方法和equals方法。
	 *  |-HashMap:底层是哈希表数据结构,允许使用null键和null值,该集合是不同步,效率高。
	 *  |-TreeMap:底层是二叉树数据结构,线程不同步,可以用于给map集合中的键进行排序。
	 *  
	 *  TreeMap和Set很想,其实,Set底层就是使用了Map集合。
	 */
	public static void main(String[] args) {
		Map<String,String> map=new HashMap<String,String>();
		
		//添加元素
		map.put("01", "zhangsan001");
		map.put("02", "zhangsan002");
		map.put("03", "zhangsan003");
		
		System.out.println("containsKey:"+map.containsKey("02"));//containsKey:true
		
		//remove方法返回值:与 key 关联的旧值;如果 key 没有任何映射关系,则返回 null。(返回 null 还可能表示该映射之前将 null 与 key 关联。)
		System.out.println("remove:"+map.remove("022"));//remove:null
		System.out.println("remove:"+map.remove("02"));//remove:zhangsan002
		
		//可以通过get方法的返回值来判断一个键是否存在。
		System.out.println("get:"+map.get("02"));//get:null
		System.out.println("get:"+map.get("03"));//get:zhangsan003
		
		//下面这两种特殊情况
		map.put(null, "aaa");
		System.out.println("get:"+map.get(null));//get:aaa
		map.put("04", null);
		System.out.println("get:"+map.get("04"));//get:null
		                                         //这行代码说明,使用get方法获取的null为空,不能说明没有这个键,也可能是映射之前将null和key关联
		
		//获取map集合中所有的值
		Collection<String> coll = map.values();//这里不要Collection<V> coll,实际使用中,要把V变成具体的类型。
		System.out.println(coll);//[zhangsan001, zhangsan003, null, aaa]
		
		//注意:添加元素时,如果出现相同的key,后添加的值会覆盖原有的键对应的值,并且返回原来的这个值。
		System.out.println(map.put("ch", "中国"));//null
		System.out.println(map.put("ch", "中华人民共和国"));//中国
		System.out.println(map);//{ch=中华人民共和国, 01=zhangsan001, 03=zhangsan003, 04=null, null=aaa}

	}

}
           

二,Map集合的两种取出方式:

package fighting;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class MapKeySet {

	/**
	 * map集合的两种取出方式:
	 * 1,keySet:将map集合中所有的键存入到Set集合,因为Set具备迭代器,
	 *           所以可以使用迭代方式取出所有的键,再根据get方法,获取每一个键对应的值
	 *           map集合没有迭代器,map集合的取出原理:将map集合转成Set,利用Set的迭代器迭代取出。
	 * 2,entrySet:返回映射中包含的映射关系的Set视图--Map.Entry<K,V>
	 * Map.Entry  其实Entry也是一个接口,他是Map接口中的一个内部接口。
	 * interface Map 
	 * {
	 * 	public static interface Entry{
	 *  	public abstract Object getKey();
	 *  	public abstract Object getValue();
	 *  }
	 * }
	 * class HashMap implements implements Map{
	 * 
	 * 	class xxx implements Map.Entry{
	 *  	public Object getKey(){};
	 *  	public Object getValue(){};
	 *  }
	 * }
	 */
	public static void main(String[] args) {
		Map<String,String> map=new HashMap<String,String>();
		//添加元素
		map.put("01", "zhangsan001");
		map.put("02", "zhangsan002");
		map.put("04", "zhangsan004");
		map.put("03", "zhangsan003");
		
		//获取map集合中所有键的Set集合
		Set<String> keySet = map.keySet();
		//获取迭代器
		Iterator<String> it = keySet.iterator();
		while(it.hasNext()){
			String key = it.next();
			System.out.println("key:"+key+" value:"+map.get(key));
		}
		/*输出结果
		 * key:01 value:zhangsan001
		 * key:03 value:zhangsan003
		 * key:04 value:zhangsan004
		 * key:02 value:zhangsan002
		 */
		
		Set<Map.Entry<String, String>> entryset = map.entrySet();
		Iterator<Map.Entry<String, String>> it1 = entryset.iterator();
		while(it1.hasNext()){
			Map.Entry<String, String> me = it1.next();
			String key = me.getKey();
			String value = me.getValue();
			System.out.println(key+":"+value);
		}
		/*输出结果
		 * 01:zhangsan001
		 * 03:zhangsan003
		 * 04:zhangsan004
		 * 02:zhangsan002
		 */

	}

}
           

三,有关Map的一个小练习:

package fighting;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import com.itheima.Student;

public class MapDemo2 {

	/**
	 * 练习:每一个学生都有对应的归属地。
	 * 学生Student,地址String
	 * 学生属性:姓名,年龄
	 * 注意:姓名和年龄相同的视为同一个学生
	 * 保证学生的唯一性。
	 * 
	 * 1,描述学生。
	 * 2,定义map容易,将学生作为键,地址作为值,存入。
	 * 3,获取map集合中的元素。
	 * 
	 */
	public static void main(String[] args) {
		HashMap<Student0627,String> hm = new HashMap<Student0627,String>();
		
		hm.put(new Student0627("zhangsan001",22), "北京");
		hm.put(new Student0627("zhangsan002",23), "河北");
		hm.put(new Student0627("zhangsan003",24), "内蒙古");
		hm.put(new Student0627("zhangsan004",25), "天津");
		
		//第一种取出方式:keySet
		Set<Student0627> keySet =hm.keySet();
		Iterator<Student0627> it = keySet.iterator();
		while(it.hasNext()){
			Student0627 stu = it.next();
			System.out.println(stu+hm.get(stu));
		}
		/*
		 * zhangsan001...22北京
		 * zhangsan004...25天津
		 * zhangsan003...24内蒙古
		 * zhangsan002...23河北
		 */
		//第二种取出方式:entrySet
		Set<Map.Entry<Student0627, String>> entrySet = hm.entrySet();
		Iterator<Map.Entry<Student0627, String>> it1 = entrySet.iterator();
		while(it1.hasNext()){
			Map.Entry<Student0627, String> me= it1.next();
			System.out.println(me.getKey()+"..."+me.getValue());
		}
		/*
		 * zhangsan001...22...北京
		 *zhangsan004...25...天津
		 *zhangsan003...24...内蒙古
		 *zhangsan002...23...河北
		 */
		//再添加一条记录,key已经存在,值不同
		hm.put(new Student0627("zhangsan001",22), "广东");
		Set<Map.Entry<Student0627, String>> entrySet2 = hm.entrySet();
		Iterator<Map.Entry<Student0627, String>> it2 = entrySet.iterator();
		while(it2.hasNext()){
			Map.Entry<Student0627, String> me= it2.next();
			System.out.println(me.getKey()+"..."+me.getValue());
		}	
		/*
		 * zhangsan001...22...广东   ----注意zhangsan001这一条归属地变成了"广东"
		 * zhangsan004...25...天津
		 * zhangsan003...24...内蒙古
		 * zhangsan002...23...河北
		 */
	}

}
//注意:类的对象不确定要存到什么集合中去,所以要保证保存到任何集合中都不会出错
//①要覆盖hashCode方法和equals方法,
//②还要实现Comparable接口,实现compareTo方法。
class Student0627 implements Comparable<Student0627>{
	private String name;
	private int age;
	public Student0627(String name,int age){
		this.name=name;
		this.age=age;
	}
	public int compareTo(Student0627 o) {
		int num = new Integer(this.age).compareTo(new Integer(o.age));
		if(num==0)
			return this.name.compareTo(o.name);
		return num;
	}
	public int hashCode(){
		return name.hashCode()+age*34;
	}
	public boolean equals(Object obj){
		if(!(obj instanceof Student0627)){
			throw new ClassCastException("类型不匹配"); 
		}
		Student0627 s =(Student0627)obj;
		
		return this.name.equals(s.name)&&this.age==s.age;	
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString(){
		return this.name+"..."+this.age;
		
	}
}
           

四,上一个小练习(MapDemo2)的需求升级:

package fighting;

import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class TreeMapDemo {

	/**
	 * MapDemo2的续:
	 * 需求:对学生对象的年龄进行升序排序。
	 * 需求2:按照学生对象的姓名升序排序
	 * 因为数据是以键值对形式存在的,所以要使用可以排序的Map集合--TreeMap
	 * 
	 */
	public static void main(String[] args) {
		//需求1
		TreeMap<Student0627,String> tm = new TreeMap<Student0627,String>();
		
		tm.put(new Student0627("bzhangsan003",23), "北京");
		tm.put(new Student0627("zhangsan001",21), "河北");
		tm.put(new Student0627("azhangsan004",24), "内蒙古");
		tm.put(new Student0627("zhangsan002",22), "天津");
		
		Set<Map.Entry<Student0627,String>> entrySet =tm.entrySet();
		Iterator<Map.Entry<Student0627,String>> it = entrySet.iterator();
		while(it.hasNext()){
			Map.Entry<Student0627,String> me =it.next();
			Student0627 stu = me.getKey();
			String addr = me.getValue();
			System.out.println(stu+"..."+addr);
		}
		/*
		 * zhangsan001...21...河北
		 * zhangsan002...22...天津
		 * bzhangsan003...23...北京
		 * azhangsan004...24...内蒙古
		 */
		//需求2:如果想按照姓名升序进行排序,可以自定义比较器,传入TreeMap构造方法
		TreeMap<Student0627,String> tm2 = new TreeMap<Student0627,String>(new StuNameComparator());
		
		tm2.put(new Student0627("bzhangsan003",23), "北京");
		tm2.put(new Student0627("zhangsan001",21), "河北");
		tm2.put(new Student0627("azhangsan004",24), "内蒙古");
		tm2.put(new Student0627("zhangsan002",22), "天津");
		
		Set<Map.Entry<Student0627,String>> entrySet2 =tm2.entrySet();
		Iterator<Map.Entry<Student0627,String>> it2 = entrySet2.iterator();
		while(it2.hasNext()){
			Map.Entry<Student0627,String> me =it2.next();
			Student0627 stu = me.getKey();
			String addr = me.getValue();
			System.out.println(stu+"..."+addr);
		}
		/*
		 * azhangsan004...24...内蒙古
		 * bzhangsan003...23...北京
		 * zhangsan001...21...河北
		 * zhangsan002...22...天津
		 */
	}

}
class StuNameComparator implements Comparator<Student0627>{

	public int compare(Student0627 s1, Student0627 s2) {
		int num  =s1.getName().compareTo(s2.getName());
		if(num==0){
			return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
		}
		return num;
	}
	
}
           

五,有关Map的第二个小练习--字母出现的次数:

package fighting;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class TreeMapDemo1 {

	/**
	 * 练习:
	 * "adsgljrgsgjfdgf"获取该字符串中的字母出现的次数。
	 * 希望打印结果:a(1)c(2)...
	 * 
	 * 通过结果发现,每一个字母都有对应的次数,
	 * 说明字母和次数之间都有映射关系。
	 * 
	 * 注意了,当发现有映射关系时,就可以选择Map集合,
	 * 因为Map集合中存放就是映射关系。
	 * 
	 * 思路:
	 * 1,将字符串转换成字符数组,因为要对每一个字符进行操作。
	 * 2,定义一个map集合,因为打印结果的字母有顺序,所以使用TreeMap集合,
	 * 3,遍历字符数组,将每一个字母作为键,去查map集合,
	 *    如果返回null,就将该字母和1存入map集合;
	 *    如果返回不是null,说明该字母在map集合内已经存在,并有对应的次数,
	 *    那么就获取该次数并自增,让后让该字母和自增后的次数覆盖到集合中,覆盖到原来的键和对应的值
	 * 4,将Map集合的数据指定的字符串形式返回
	 */
	public static void main(String[] args) {
		String str = carCount("adsgljrgsgjfdgf");
		System.out.println(str);

	}

	public static String carCount(String str){
		char[] chs = str.toCharArray();
		TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();
		int count=0;
		for(int x=0;x<chs.length;x++){
			if(chs[x]>='a'&&chs[x]<='z'||chs[x]>='A'&&chs[x]<='Z'){//非字母不用计算个数
				continue;
			}
			Integer value = tm.get(chs[x]);
			//方法二
			if(value!=null){//不等于空,说明已经存在这个key,那么把key对应的值赋给count,再加一
				count = value;
			}
			count++;
			tm.put(chs[x], count);
			count =0;
			//方法一
			/*if(value==null){
				value = 1;
				tm.put(chs[x], 1);
			}else{
				value++;
				tm.put(chs[x], value);
			}*/
		}
		StringBuilder sb = 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();
			Character ch = me.getKey();
			Integer value = me.getValue();
			sb.append(ch+"("+value+")");
		}
		return sb.toString();//把sb转换成字符串类型返回,这里toString不能省略
	}
}
           

六,Map扩展知识:大集合嵌套小集合、一对多映射

package fighting;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;


public class MapDemo1 {

	/**
	 * Map扩展知识:
	 * map集合被使用是因为具备映射关系。。
	 * 
	 * 需求:一个学校有多个班级,每个班级有多名学生,利用Map遍历所有学生
	 * 比如:学校有预热班和就业班
	 * "预热班","1号","张三"
	 * "预热班","2号","李四"
	 * "就业班","1号","张三"
	 * "就业班","2号","李四"
	 * 
	 * 需求2:把学号和学生姓名封装成学生对象进行操作。
	 * 
	 * 大集合里嵌套小集合
	 * 一对多映射
	 */
	public static void main(String[] args) {
		//分别定义学校、预热班、就业班
		HashMap<String,HashMap<String,String>> school = new HashMap<String,HashMap<String,String>>();
		HashMap<String,String> yure=new HashMap<String,String>();
		HashMap<String,String> jiuye =new HashMap<String,String>();
		//把班级信息添加到学校集合
		school.put("预热班", yure);
		school.put("就业班", jiuye);
		//把学生信息添加到班级集合
		yure.put("1号", "张三");
		yure.put("2号", "李四");
		//把学生信息添加到班级集合
		jiuye.put("1号", "张三er");
		jiuye.put("2号", "李四er");
		//遍历输出,
		Iterator<String> it = school.keySet().iterator();//获取学校的所有班级信息
		while(it.hasNext()){
			String roomName = it.next();//班级名称--预热班、就业班
			HashMap<String,String> room = school.get(roomName);//班级对应的集合--yure、jiuye
			Iterator<String> it1 = room.keySet().iterator();//班级里学生信息的学号集合
			while(it1.hasNext()){
				String id = it1.next();//学号
				System.out.println(roomName+id+"::"+room.get(id));
			}
			
		}
		System.out.println("---------------------------把学生封装成对象(Student27)实现如下--------------------------------");
		demo();
		
	}
	public static void demo(){
		//把学生信息保存到List集合里,就是说每一个班级对应一个学生的List集合,
		//获取班级信息后,就可以获取学生的一个List集合,再迭代这个List集合就可以得到所有学生信息。
		HashMap<String,List<Student27>> hm = new HashMap<String,List<Student27>>();
		
		List<Student27> yure = new ArrayList<Student27>();
		List<Student27> jiuye = new ArrayList<Student27>();

		hm.put("预热班", yure);
		hm.put("就业班", jiuye);
		
		yure.add(new Student27("1号", "张三"));
		yure.add(new Student27("2号", "李四"));
		jiuye.add(new Student27("1号", "张三er"));
		jiuye.add(new Student27("2号", "李四er"));
		
		
		Iterator<String> it = hm.keySet().iterator();
		while(it.hasNext()){
			String roomName = it.next();
			List<Student27> room = hm.get(roomName);
			Iterator<Student27> it1 = room.iterator();
			while(it1.hasNext()){
				Student27 stu = it1.next();
				System.out.println(roomName+stu.getId()+"::"+stu.getName());
			}
			
		}
		
	}

}
//把学号和学生姓名封装成学生对象--学生类
class Student27 {
	private String id;
	private String name;
	public Student27(String id,String name){
		this.id=id;
		this.name=name;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
}