Map 接口

Map 接口(双列集合的根接口)
1.以键值对形式保存数据
2.键和值一一映射,可以通过键来获取值

注意:
给定一个键和一个值,你可以将该值存储在一个Map对象. 之后,你可以通过键来访问对应的值。
当访问的值不存在的时候,方法就会抛出一个NoSuchElementException异常.
当对象的类型和Map里元素类型不兼容的时候,就会抛出一个 ClassCastException异常。
当在不允许使用Null对象的Map中使用Null对象,会抛出一个NullPointerException 异常。
当尝试修改一个只读的Map时,会抛出一个UnsupportedOperationException异常。
map 的添加方法
HashMap<String,Integer> map = new HashMap<>();
Integer i1 = map.put("甲", 30);
Integer i2 = map.put("乙", 40);
Integer i3 = map.put("丙", 20);
System.out.println(map);				// {甲=30, 乙=40, 丙=20}
Integer i4 = map.put("丙", 80);
// Integer 返回的是被覆盖的值,没被覆盖时,返回 null
System.out.println(i1);					// null
System.out.println(i2);					// null
System.out.println(i3);					// null
System.out.println(i4);					// 20
System.out.println(map);				// {甲=30, 乙=40, 丙=80}

Map 基本方法

HashMap<String, Integer> map = new HashMap<>();
map.put("甲", 30);
map.put("乙", 20);
map.put("丙", 20);
// 是否包含 key
boolean containsKey = map.containsKey("甲");
System.out.println(containsKey);		// true
// 是否包含 value
boolean containsValue = map.containsValue(20);
System.out.println(containsValue);		// true
// 通过 key 获取对应 value
Integer integer1 = map.get("甲");		
Integer integer2 = map.get("丁");
System.out.println(integer1);			// 30
System.out.println(integer2);			// null
// 获取所有 key 的 Set 集合
Set<String> keySet = map.keySet();
System.out.println(keySet);				// [甲, 乙, 丙]
// 获取所有 value 的集合
Collection<Integer> values = map.values();
System.out.println(values);				// [30, 20, 20]
// 通过 key 删除整个键值对
Integer remove = map.remove("乙");
Integer remove2 = map.remove("丁");
System.out.println(remove);				// 20
System.out.println(remove2);			// null
// 清空 map
map.clear();
System.out.println(map);				// {}
Student 类:
public class Student implements Comparable<Student>{
	private String name;
	private int age;
	public Student() {
		super();
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = 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 int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	@Override
	public String toString() {
		return "[ 姓名 : " + name + " , 年龄 : " + age + " ]";
	}
	
	@Override
	public int compareTo(Student o) {
		int num = this.age - o.getAge();
		return num == 0 ? 1 : num;
	}
	
}
// 创建一个 map , key 保存学生, value 保存户籍
HashMap<Student, String> map = new HashMap<>();
map.put(new Student("鹏", 21), "安徽");
map.put(new Student("北", 22), "河南");
map.put(new Student("轩", 23), "江苏");
// 去重(重写 hashCode 和 equals 方法)
// 重写之后,key 相同, value 会被新值覆盖
map.put(new Student("北", 22), "河北");
System.out.println(map);			// {[ 姓名 : 北 , 年龄 : 22 ]=河北, [ 姓名 : 轩 , 年龄 : 23 ]=江苏, [ 姓名 : 鹏 , 年龄 : 21 ]=安徽}

遍历 Map

迭代器遍历
HashMap<String, Integer> map = new HashMap<>();
map.put("甲", 30);
map.put("乙", 40);
map.put("丙", 20);
map.put("丁", 20);
// 通过 keySet 遍历
// 取出所有 key 的 Set 集合
Set<String> keySet = map.keySet();
// 获取迭代器
Iterator<String> iterator = keySet.iterator();
// 遍历所有 key
while (iterator.hasNext()) {
	String key = iterator.next();
	// 通过 key 获取对应 vlaue
	Integer integer = map.get(key);
	System.out.println("[ " + key + " : " + integer + " ]");
}
/*
 * [ 丁 : 20 ]
 * [ 甲 : 30 ]
 * [ 乙 : 40 ]
 * [ 丙 : 20 ]
 */
增强 for 循环遍历
HashMap<String, Integer> map = new HashMap<>();
map.put("甲", 30);
map.put("乙", 40);
map.put("丙", 20);
map.put("丁", 20);
Set<String> keySet = map.keySet();
for (String key : keySet) {
	Integer integer = map.get(key);
	System.out.println("[ " + key + " : " + integer + " ]");
}
/*
 * [ 丁 : 20 ]
 * [ 甲 : 30 ]
 * [ 乙 : 40 ]
 * [ 丙 : 20 ]
 */
通过获取键值对对象的 set 集合来遍历
HashMap<String, Integer> map = new HashMap<>();
map.put("甲", 30);
map.put("乙", 40);
map.put("丙", 20);
map.put("丁", 20);
// Entry 是 Map 中的内部接口,需要用 Map 来调用 Entry 所以是 Map. 系统自动生成时省略
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
// 获取迭代器
Iterator<Map.Entry<String, Integer>> iterator = entrySet.iterator();
while (iterator.hasNext()) {
	// 获取 Entry 对象
	Entry<String, Integer> entry = iterator.next();
	// 获取 key
	String key = entry.getKey();
	// 获取 value
	Integer value = entry.getValue();
	System.out.println("[ " + key + " : " + value + " ]");// 或者 System.out.println(entry);
}

/*
 * [ 丁 : 20 ]
 * [ 甲 : 30 ]
 * [ 乙 : 40 ]
 * [ 丙 : 20 ]
 */

内部接口如:
interface InterA{
	// InterB 是 InterA 的内部接口
	interface InterB{
		public abstract void fun();
	}
}
// 创建一个类,实现 InterB 接口
// 
class InterBImpl implements InterA.InterB{
	@Override
	public void fun() {
		
	}
}
HashMap<String, Integer> map = new HashMap<>();
map.put("甲", 30);
map.put("乙", 20);
map.put("丙", 20);
map.put("丁", 20);
for (Entry<String, Integer> entry : map.entrySet()) {
	String key = entry.getKey();
	Integer value = entry.getValue();
	System.out.println("[ " + key + " : " + value + " ]");
}
/*
 * [ 丁 : 20 ]
 * [ 甲 : 30 ]
 * [ 乙 : 40 ]
 * [ 丙 : 20 ]
 */
键盘输入字符串 统计字符串中每个字符出现的次数 
System.out.println("请输入字符串");
Scanner scanner = new Scanner(System.in);
String string = scanner.nextLine();
// 转字符数组,为了取出每一个字符
char[] charArray = string.toCharArray();
// 创建 map
HashMap<Character, Integer> map = new HashMap<>();
// 遍历
for (int i = 0; i < charArray.length; i++) {
	// 将每一个字符存入 map 中
	// 判断要存的字符是否存在于 map 中
	char key = charArray[i];
	Integer value = map.get(key);
	if (value == null) {
		// key 不存在 map 中
		map.put(key, 1);
	} else {
		// key 存在于 map 中
		// 利用 key 把对应值取出来 + 1
		Integer v = map.put(charArray[i], 1);
		// 重新存回去,覆盖原先 value 的部分
		map.put(key, v + 1);
	}
}
System.out.println(map);
scanner.close();
// 请输入字符串
// asddwqdsadqwdsdgvfgdhjsfgjdfggdsgf
// {a=2, q=2, s=5, d=9, v=1, f=4, w=2, g=6, h=1, j=2}

LindedHashMap

LinkedHashMap
特点:有序(怎么存储,怎么打印)
LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
map.put("鹏", 18);
map.put("忠", 22);
map.put("水", 20);
map.put("茜", 28);
System.out.println(map);			// {鹏=18, 忠=22, 水=20, 茜=28}
// 创建一个 treemap key 保存学生, value 保存户籍
// 按年龄排序
TreeMap<Student, String> map = new TreeMap<>();
map.put(new Student("鹏", 21), "安徽");
map.put(new Student("北", 22), "河南");
map.put(new Student("轩", 23), "江苏");
map.put(new Student("水", 18), "浙江");
for (Entry<Student, String> entry : map.entrySet()) {
	Student key = entry.getKey();
	String value = entry.getValue();
	System.out.println("[ " + key + " 来自 : " + value + " ]");
}
/*
 * [ [ 姓名 : 水 , 年龄 : 18 ] 来自 : 浙江 ]
 * [ [ 姓名 : 鹏 , 年龄 : 21 ] 来自 : 安徽 ]
 * [ [ 姓名 : 北 , 年龄 : 22 ] 来自 : 河南 ]
 * [ [ 姓名 : 轩 , 年龄 : 23 ] 来自 : 江苏 ]
 */
// Collection 类中的方法(静态方法)
ArrayList<Integer> list  = new ArrayList<>();
list.add(12);// 自动装箱
list.add(10);
list.add(84);
list.add(20);
list.add(24);
list.add(36);
list.add(42);
list.add(57);
System.out.println(list);			// [12, 10, 84, 20, 24, 36, 42, 57]

// 随机交换集合中值得位置(洗牌)
Collections.shuffle(list);
System.out.println(list); 			// [12, 42, 24, 84, 20, 10, 36, 57]

// 排序
Collections.sort(list);
System.out.println(list);			// [10, 12, 20, 24, 36, 42, 57, 84]

// 二分查找
int index = Collections.binarySearch(list, 36);
System.out.println(index);			// 4

// 反转集合
Collections.reverse(list);
System.out.println(list);			// [84, 57, 42, 36, 24, 20, 12, 10]
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("北", 22));
list.add(new Student("鹏", 21));
list.add(new Student("轩", 23));
// 排序(对象排序时,需要实现 Comparable 接口,编写排序规则)
Collections.sort(list);
System.out.println(list);			// [[ 姓名 : 鹏 , 年龄 : 21 ], [ 姓名 : 北 , 年龄 : 22 ], [ 姓名 : 轩 , 年龄 : 23 ]]
/*
 * 使用 ArrayList 模拟三人斗地主
 * 1.洗牌
 * 2.发牌
 * 3.看牌
 * 分析:
 * 1.先创建一副牌(使用 ArrayList)
 * 2.洗牌(suffle)
 * 3.发牌分三人(三个 list)和底牌部分(list)
 * 4.看牌(打印 list)
 * 
 */
 public class Demo {
	public static void main(String[] args) {
		ArrayList<String> poker = new ArrayList<>();
		// 拼接字符串
		String[] AllColors = {"黑桃","红桃","梅花","方片"};  
        String[] AllNum = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};  
        for (String colors : AllColors) {
			for (String num : AllNum) {
				// 拼接字符串
				String pokerStr = colors + num;
				// 把牌装进集合中
				poker.add(pokerStr);
			}
		}
        // 添加大小王
        poker.add("小王");
        poker.add("大王");
        // 洗牌
        	Collections.shuffle(poker);
        	// 创建4个装牌的集合
        	// 0  3  6  9
        	ArrayList<String> list1 = new ArrayList<>();
    		ArrayList<String> list2 = new ArrayList<>();
    		ArrayList<String> list3 = new ArrayList<>();
    		ArrayList<String> list4 = new ArrayList<>();
        	// 遍历牌的集合
        	for (int i = 0; i < poker.size(); i++) {
			// 把每一张牌取出来
        		String pokers = poker.get(i);
        		// 按发牌顺序添加不同集合中
        		if (i > 50) {
				// 51 52 53
        			list4.add(pokers);
			} else if (i % 3 == 0) {
				// 给第一个人发牌
				list1.add(pokers);
			} else if (i % 3 == 1) {
				// 给第二个人发牌
				list2.add(pokers);
			}else{
				// 给第三个人发牌
				list3.add(pokers);
			}
		}
		System.out.println("鹏的手牌:");
       	System.out.println(list1);
       	System.out.println("水的手牌:");
       	System.out.println(list2);
       	System.out.println("孟的手牌:");
       	System.out.println(list3);
       	System.out.println("底牌:");
       	System.out.println(list4);
	}
}
/*
 * 鹏的手牌:
 * [方片9, 黑桃Q, 梅花9, 方片3, 黑桃J, 黑桃9, 方片4, 红桃A, 黑桃A, 梅花7, 方片K, 方片10, 梅花8, 黑桃6, 黑桃3, 黑桃7, 黑桃5]
 * 水的手牌:
 * [红桃J, 方片7, 梅花10, 方片2, 红桃10, 梅花A, 大王, 梅花2, 方片Q, 红桃8, 红桃9, 红桃5, 黑桃4, 方片8, 梅花6, 方片A, 红桃3]
 * 孟的手牌:
 * [梅花J, 红桃7, 小王, 黑桃K, 红桃K, 梅花5, 黑桃10, 红桃4, 梅花K, 红桃2, 方片J, 梅花4, 红桃6, 红桃Q, 梅花Q, 方片5, 方片6]
 * 底牌:
 * [黑桃8, 梅花3, 黑桃2]
 */
/*
 * 使用 map 模拟三人斗地主
 * 1.洗牌
 * 2.发牌
 * 3.看牌
 */
public class Demo {
	public static void main(String[] args) {
		// 创建 map 集合
		HashMap<Integer, String> poker = new HashMap<>();
		// 创建一个集合,保存索引
		ArrayList<Integer> list = new ArrayList<>();
		// 创建牌的索引
		int index = 1;
		// 拼接字符串
		String[] AllColors = {"黑桃","红桃","梅花","方片"};  
		String[] AllNum = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};  
		for (String  num: AllNum) {
			for (String colors : AllColors) {
				// 拼接字符串
				String string = colors + num;
				// 把牌装进集合中
				poker.put(index, string);
				// 把索引装进 list 中(为洗牌准备)
				list.add(index);
				// 让索引自增
				index++;
			}
		}
		// map 中添加大小王,list 中添加 index,index 自增
		poker.put(index, "小王");
		list.add(index++);
		poker.put(index, "大王");
		list.add(index);
		// 洗牌(随机排序索引)
		Collections.shuffle(list);
		// 发牌(将索引发出去)
		// 创建4个 TreeSet 保存索引
		TreeSet<Integer> set1 = new TreeSet<>();
		TreeSet<Integer> set2 = new TreeSet<>();
		TreeSet<Integer> set3 = new TreeSet<>();
		TreeSet<Integer> set4 = new TreeSet<>();
		// 发牌(发索引)
		for (int i = 0; i < list.size(); i++) {
			// 取出每个索引
			Integer integer = list.get(i);
			// 按顺序发牌
			if (i > 50) {
				set4.add(integer);
			} else if (i % 3 == 0) {
				// 给第一个人发牌
				set1.add(integer);
			} else if (i % 3 == 1) {
				// 给第二个人发牌
				set2.add(integer);
			}else{
				// 给第三个人发牌
				set3.add(integer);
			}
		}
		// 看牌(去 map 中使用索引把对应的牌取出来打印)
		lookPokers(poker, set1, "鹏");
		lookPokers(poker, set2, "水");
		lookPokers(poker, set3, "龙");
		lookPokers(poker, set4, "底牌");
	}
	// 看牌的方法
	public static void lookPokers(HashMap<Integer, String> map, TreeSet<Integer> set, String name) {
		if (!name.equals("底牌")) {
			System.out.println(name + "的手牌:");
		} else {
			System.out.println("底牌:");
		}
		// 遍历索引的 set, 取出每一个索引,再去 map 中找到对应的牌
		for (Integer key : set) {
			// 取出的牌
			String string = map.get(key);
			System.out.print(string + " ");
		}
		System.out.println();
	}
}
/*
 * 鹏的手牌:
 * 梅花3 黑桃4 方片4 梅花5 方片5 方片6 红桃7 梅花7 黑桃10 梅花10 红桃J 方片Q 梅花K 方片K 红桃2 方片2 小王 
 * 水的手牌:
 * 方片3 红桃4 梅花4 黑桃5 黑桃6 梅花6 黑桃7 红桃8 梅花8 方片9 红桃10 梅花J 方片J 红桃Q 黑桃K 黑桃A 红桃A 
 * 龙的手牌:
 * 红桃3 红桃5 红桃6 方片8 黑桃9 红桃9 梅花9 方片10 黑桃J 黑桃Q 梅花Q 红桃K 梅花A 方片A 黑桃2 梅花2 大王 
 * 底牌:
 * 黑桃3 方片7 黑桃8 
 */

Map 的嵌套

/*
 * Java学科
 * java 1班  -- 保存是学生 和 户籍
 * java 2班  -- 保存是学生 和 户籍
 * 
 * Java学科 是一个map
 * 保存了两个键值对 ----  1班 和 2班
 * 
 * 1班 也是一个 map
 * 保存 ----  学生 户籍
 */
public class Demo {
	public static void main(String[] args) {
		HashMap<Student, String> class1 = new HashMap<>();// 1班
		HashMap<Student, String> class2 = new HashMap<>();// 2班
		HashMap<HashMap<Student, String>, String> subject = new HashMap<>();// 学科
		class1.put(new Student("鹏", 21), "安徽");
		class1.put(new Student("北", 22), "河南");
		class1.put(new Student("剑", 20), "江苏");
		class2.put(new Student("轩", 23), "江苏");
		class2.put(new Student("水", 19), "浙江");
		class2.put(new Student("孟", 18), "浙江");
		subject.put(class1, "Java1班");
		subject.put(class2, "Java2班");
		// 遍历学科,找到班
		for (HashMap<Student, String> classes : subject.keySet()) {
			// 先获取学科的 value
			String subjectValue = subject.get(classes);
			System.out.println(subjectValue + ":");
			// 遍历班,打印学生和对应户籍
			for (Student student : classes.keySet()) {
				// 打印班对应的 value(学生的户籍)
				String classesValue = classes.get(student);
				System.out.println(student + " 户籍 : " + classesValue);
			}
			System.out.println();
		}
	}
}
/*
 * Java1班:
 * [ 姓名 : 北 , 年龄 : 22 ] 户籍 : 河南
 * [ 姓名 : 鹏 , 年龄 : 21 ] 户籍 : 安徽
 * [ 姓名 : 剑 , 年龄 : 20 ] 户籍 : 江苏
 *
 * Java2班:
 * [ 姓名 : 水 , 年龄 : 19 ] 户籍 : 浙江
 * [ 姓名 : 轩 , 年龄 : 23 ] 户籍 : 江苏
 * [ 姓名 : 孟 , 年龄 : 18 ] 户籍 : 浙江
 */