Map集合

Map集合

Map集合概述

一.Map接口概述

  • java.util包下的,使用时需要导包
  • 将键映射到值得对象
  • 一个映射不能包含重复的键
  • 每个键最多只能映射到一个值

二.Map接口和Collection接口的不同

  • Map是双列的,Collection是单列的
  • Map的键唯一,Collection的子体系Set是唯一的
  • Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素有效

Map集合的功能概述

1.添加功能

  • V put(K key,V value):添加元素

如果键是第一次存储,就直接存储元素,返回null
如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值

2.删除功能

  • void clear(): 移除所有的键值对元素
  • V remove(Object key):根据键删除删除键值对元素,并把值返回

3.判断功能

  • boolean containsKey(Object key):判断集合是否包含指定的键
  • boolean containsValue(Object value):判断集合是否包含指定的值
  • boolean isEmpty():判断集合是否为空

4.获取功能

  • Set<Map.Entry<K,V>> entrySet():(Map.Entry<K,V>泛型) 获取键值对对象
  • V get(Object key):根据键获取值
  • Set KeySet():获取集合中所有键的集合
  • Collection values():获取集合中所有值的集合

案例演示


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

public class Demo1_Map {
	public static void main(String[] args) {
		//demo1();
		//demo2();
		Map<String, Integer> map = new HashMap<>();
		map.put("张三", 23);
		map.put("李四", 24);
		map.put("王五", 25);
		map.put("赵六", 26);
		
		Collection<Integer> c = map.values();
		System.out.println(c);             //[24, 23, 25, 26]存储不按顺序,每次运行结果不同
		System.out.println(map.size());    //4
	}

	public static void demo2() {
		Map<String, Integer> map = new HashMap<>();
		map.put("张三", 23);
		map.put("李四", 24);
		map.put("王五", 25);
		map.put("赵六", 26);
		
		//Integer value = map.remove("张三");       //根据键删除元素,返回键对应的值
		//System.out.println(value);
		System.out.println(map.containsKey("张三"));//判断是否包含传入的键true
		System.out.println(map.containsValue(23));  //判断是否包含传入的值true
		System.out.println(map);
	}

	public static void demo1() {
		Map<String, Integer>map = new HashMap<>();
		Integer i1 = map.put("张三", 23);       //覆盖的值23
		Integer i5 = map.put("张三", 26);       //相同的键("张三")不存储,值(23)覆盖,返回被覆盖的值
		Integer i2 = map.put("李四", 24);
		Integer i3 = map.put("王五", 25);
		Integer i4 = map.put("赵六", 26);
		
		System.out.println(map);
		
		System.out.println(i1);         
		System.out.println(i2);
		System.out.println(i3);
		System.out.println(i4);
		System.out.println(i5);//23
	}

}

Map集合遍历之键找值

1.通过查看Map集合的API发现没有iterator方法,那么双列集合如何迭代呢?

  • 使用增强for循环遍历
  • 根据键获取值

案例演示


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

public class Demo2_Iterator {
	public static void main(String[] args) {
		Map<String, Integer> map = new HashMap<>();
		map.put("张三", 23);
		map.put("李四", 24);
		map.put("王五", 25);
		map.put("赵六", 26);
		
		Set<String> keySet = map.keySet();           //获取所有键的集合
		Iterator<String> it = keySet.iterator();
		while (it.hasNext()) {                       //判断集合中是否有元素
			String key = it.next();                  //获取每一个元素
			Integer value = map.get(key);            //根据键获取值
			System.out.println(key + "=" + value);
		}
		
		//使用增强for循环遍历
		/*for (String key : map.keySet()) {
			System.out.println(key + "=" + map.get(key));
		}*/
	}

}

Map集合遍历之键值对对象找键和值

1.解释Map.Entry

  • Map.Entry说明Entry是Map的内部接口,将键和值封装成了Entry对象,并存储在Set集合中

2.方法

  • 增强for循环
  • 键值对对象找键和值

案例演示

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


public class Demo3_Iterator {
	public static void main(String[] args) {
		Map<String, Integer> map = new HashMap<>();
		map.put("张三", 23);
		map.put("李四", 24);
		map.put("王五", 25);
		map.put("赵六", 26);
		/*//Map.Entry说明Entry是Map的内部接口,将键和值封装成了Entry对象,并存储在Set集合中
		Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
		//获取每一个对象
		Iterator<Map.Entry<String, Integer>> it = entrySet.iterator();
		while (it.hasNext()) {
			//获取每一个Entry对象
			Map.Entry<String, Integer> en = it.next();
			String key = en.getKey();
			Integer value = en.getValue();
			System.out.println(key + "=" + value);
			}*/
		
		//增强for循环
		for (Map.Entry<String,Integer> en : map.entrySet()) {
			System.out.println(en.getKey() + "=" + en.getValue());
		}
	}

}

HashMap集合键是Student,值是String

  • 键是学生对象,代表每一个学生
  • 值是字符串对象,代表学生归属地

案例演示


import java.util.HashMap;
import com.heima.bean.Student;

public class Demo5_HashMap {
	public static void main(String[] args) {
		HashMap<Student, String> hm = new HashMap<>();
		hm.put(new Student("张三",23),"北京");//往HashSet集合中存储时要在Student类中重写其中的hashCode()与equals()方法
		hm.put(new Student("张三",23),"上海");//如果不重写会存储重复元素
		hm.put(new Student("李四",24),"广州");
		hm.put(new Student("王五",25),"深圳");
		
		System.out.println(hm);
		//{Student [name=张三, age=23]=上海, Student [name=李四, age=24]=广州, Student [name=王五, age=25]=深圳}因为键不是第一次存储所以用上海把北京替换掉
	}
}

LinkedHashMap

一.特点

  • 底层是链表实现的,可以保证怎么存就怎么取

TreeMap集合键是Student,值是String

1.自然顺序(Comparable)

  • 在Student类中重写compareTo()方法,定义比较方式
    @Override
	public int compareTo(Student o) {
		int num = this.age - o.age;//以年龄排序
		return num == 0 ? this.name.compareTo(o.name) : num;
	}

2.比较器顺序(Comparator)

  • 创建TreeSet的时候传入Comparator的子类对象,或者传入匿名内部类重写compare()方法
TreeMap<Student, String> tm = new TreeMap<>(new Comparator<Student>() {
   @Override
   public int compare(Student s1, Student s2) {
      int num = s1.getName().compareTo(s2.getName());//按姓名比较
	  return num == 0 ? s1.getAge() - s2.getAge() : num;
	}
});

案例演示


import java.util.Comparator;
import java.util.TreeMap;
import com.heima.bean.Student;

public class Demo7_TreeMap {
	public static void main(String[] args) {
		//demo1();
		TreeMap<Student, String> tm = new TreeMap<>(new Comparator<Student>() {

			@Override
			public int compare(Student s1, Student s2) {
				int num = s1.getName().compareTo(s2.getName());//按姓名比较
				return num == 0 ? s1.getAge() - s2.getAge() : num;
			}
		});
		tm.put(new Student("张三",23), "北京");
		tm.put(new Student("李四",24), "上海");
		tm.put(new Student("王五",25), "广州");
		tm.put(new Student("赵六",26), "深圳");
		
		System.out.println(tm);//按姓输出 张 李 王 赵
	}

	public static void demo1() {
		TreeMap<Student, String> tm = new TreeMap<>();
		tm.put(new Student("张三",23), "北京");
		tm.put(new Student("李四",24), "上海");
		tm.put(new Student("王五",25), "广州");
		tm.put(new Student("赵六",26), "深圳");
		
		System.out.println(tm);//按年龄排序输出的
	}

}

集合嵌套之HashMap嵌套HashMap

一. 需求:

双园课堂

  • 第88期第99期两个基础班定义成一个双列集合,键是学生对象,值是学生归属地
  • 不论88还是99班级都是班级对象,所以为了统一管理,把这些对象都添加到双园课堂集合中

案例演示

import java.util.HashMap;

import com.heima.bean.Student;

public class Demo8_HashMap_HashMap {
	/*
	   集合嵌套之HashMap嵌套HashMap
	   需求:
	   双园课堂
	   第88期第99期两个基础班定义成一个双列集合,键是学生对象,值是学生归属地
	   不论88还是99班级都是班级对象,所以为了统一管理,把这些对象都添加到双园课堂集合中
	 */
	public static void main(String[] args) {
		HashMap<Student, String> hm88 = new HashMap<>();
		hm88.put(new Student("张三",23), "北京");
		hm88.put(new Student("李四",24), "北京");
		hm88.put(new Student("王五",25), "上海");
		hm88.put(new Student("赵六",26), "广州");
		
		HashMap<Student, String> hm99 = new HashMap<>();
		hm99.put(new Student("唐僧",1023), "北京");
		hm99.put(new Student("孙悟空",1024), "北京");
		hm99.put(new Student("猪八戒",1025), "上海");
		hm99.put(new Student("沙和尚",1026), "广州");
		
		HashMap<HashMap<Student, String>, String> hm = new HashMap<>();
		hm.put(hm88, "第88期基础班");
		hm.put(hm99, "第99期基础班");
		
		//遍历双列集合
		for ( HashMap<Student, String> key1 : hm.keySet()) {//hm.keySet()代表的是双列集合中键的集合
			String value1 = hm.get(key1);                   //根据键对象获取值
			//遍历键的双列集合对象
			for (Student key2 : h.keySet()) {               //h.keySet()是获取集合中所有的学生
				String value2 = h.get(key2);
				
				System.out.println(key2 + " = " + value2  + " = " + value1);
			}
		}
	}

}

面试题:HashMap和Hashtable的区别

一.共同点:

  • 底层都是哈希算法,都是双列集合

二.区别:

区别1:

  • HashMap是线程不安全的,效率高,JDK1.2版本的
  • Hashtable是线程安全的,效率低,JDK1.0版本的

区别2:

  • HashMap可以存储null键和null值
  • Hashtable不可以存储null键和null值

案例演示


import java.util.HashMap;
import java.util.Hashtable;

public class Demo9_Hashtable {
	public static void main(String[] args) {
		HashMap<String, Integer> hm = new HashMap<>();
		hm.put(null, 23);
		hm.put("张三", null);
		System.out.println(hm);
		
		Hashtable<String, Integer> ht = new Hashtable<>();
//		ht.put(null, 23);      报错java.lang.NullPointerException
//		ht.put("张三", null);
//		System.out.println(ht);
	}

}

Collections工具类

一.Collectiion类的概述

  • 针对集合操作的工具类

二.Collections成员方法

  • public static void sort(List list):对List集合排序
  • public static int binarySearch(List<?> list,T key):二分查找
  • public static T max(Collection<?> coll):根据默认排序结果获取集合中的最大值
  • public static void reverse(List<?> list):反转集合
  • public static void shuffle(List<?> list):随机置换,可以用来洗牌

案例演示


import java.util.ArrayList;
import java.util.Collections;

public class Demo1_Collections {
	public static void main(String[] args) {
		//demo1();
		//demo2();
		ArrayList<String> list = new ArrayList<>();
		list.add("a");
		list.add("c");
		list.add("d");
		list.add("f");
		list.add("g");
		System.out.println(Collections.max(list));  //根据默认排序结果获取集合中的最大值
		Collections.reverse(list);                  //反转集合
		System.out.println(list);
		Collections.shuffle(list);                  //随机置换,可以用来洗牌
		System.out.println(list);
	}

	public static void demo2() {
		ArrayList<String> list = new ArrayList<>();
		list.add("a");
		list.add("c");
		list.add("f");
		list.add("d");
		list.add("g");
		
		System.out.println(Collections.binarySearch(list, "c"));//1
		System.out.println(Collections.binarySearch(list, "b"));
		//-2 因为集合中不存在b所以按照集合顺序应该在a后c前插入,索引为1 ,-2 = 插入点索引 - 1
		System.out.println(Collections.binarySearch(list, "e"));//-3
	}

	public static void demo1() {
		ArrayList<String> list = new ArrayList<>();
		list.add("c");
		list.add("a");
		list.add("a");//重复保留
		list.add("b");
		list.add("d");
		
		System.out.println(list);
		Collections.sort(list);//对List集合排序
		System.out.println(list);
	}

}

模拟斗地主

一.分析

  1. 创建HashMap集合,键存储索引,值存储牌的属性
  2. 创建ArrayList集合存储索引,洗牌则为洗索引
  3. 洗牌:通过Collections中的shuffle()方法
  4. 创建TreeSet集合存储代表三个人和底牌,因为TreeSet集合会自动对索引进行排序
  5. 发牌
  6. 看牌,ArrayList中存储的索引找HashMap中的值

案例演示


import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;

public class Test3 {
	public static void main(String[] args) {
		String[] num = {"3","4","5","6","7","8","9","10","J","Q","K","A","2",};//按顺序放
		String[] color = {"红桃","黑桃","方片","梅花"};
		HashMap<Integer, String> hm = new HashMap<>();   //存储索引和值
		ArrayList<Integer> list = new ArrayList<>();     //存储索引
		int index = 0;
		
		//拼接扑克牌并将索引存储在HashMap中
		for (String s1 : num) {                         //获取数字
			for (String s2 : color) {                   //获取花色
				hm.put(index, s2.concat(s1));
				list.add(index);                        //将索引添加到list集合中
				index++;
			}
		}
		
		//将大小王添加
		hm.put(index, "小王");
		list.add(index);
		index++;
		hm.put(index, "大王");
		list.add(index);
		
		//洗牌
		Collections.shuffle(list);                      //洗索引
		
		//发牌
		TreeSet<Integer> gaojin = new TreeSet<>();
		TreeSet<Integer> longwu = new TreeSet<>();
		TreeSet<Integer> me = new TreeSet<>();
		TreeSet<Integer> dipai = new TreeSet<>();
		
		for (int i = 0; i < list.size(); i++) {
			if (i >= list.size() - 3) {
				dipai.add(list.get(i));
			} else if (i % 3 == 0) {
				gaojin.add(list.get(i));
			} else if (i % 3 == 1) {
				longwu.add(list.get(i));
			} else {
				me.add(list.get(i));
			}
		}
		
		//看牌
		lookPoker(hm, gaojin, "高进");
		lookPoker(hm, longwu, "龙武");
		lookPoker(hm, me, "雷佳辉");
		lookPoker(hm, dipai, "底牌");
	}

	public static void lookPoker(HashMap<Integer, String> hm,TreeSet<Integer> ts,String name) {
		System.out.println(name + "的牌是:");
		for (Integer i : ts) {
			System.out.print(hm.get(i) + " ");
		}
		System.out.println();
	}
}

泛型固定上下边界

一.泛型固定下边界

  • 泛型固定下边界

二.泛型固定上边界

  • ? extends E

案例演示


import java.util.ArrayList;
import java.util.Comparator;
import java.util.TreeSet;
import com.heima.bean.BaseStudent;
import com.heima.bean.Student;

public class Demo2_Genric {
	public static void main(String[] args) {
		//demo1();
		TreeSet<Student> ts1 = new TreeSet<>(new CompareByAge());
		ts1.add(new Student("张三",33));
		ts1.add(new Student("李四",13));
		ts1.add(new Student("王五",23));
		ts1.add(new Student("赵六",43));
		
		TreeSet<BaseStudent> ts2 = new TreeSet<>(new CompareByAge());
		ts2.add(new BaseStudent("张三",33));
		ts2.add(new BaseStudent("李四",13));
		ts2.add(new BaseStudent("王五",23));
		ts2.add(new BaseStudent("赵六",43));
		
		System.out.println(ts1);
		System.out.println(ts2);                    //子类BaseStudent可以用父类Student的比较器
	}

	public static void demo1() {
		//? extends E
		ArrayList<Student> list1 = new ArrayList<>();
		list1.add(new Student("张三",23));
		list1.add(new Student("李四",24));
		
		ArrayList<BaseStudent> list2 = new ArrayList<>();
		list2.add(new BaseStudent("王五",25));
		list2.add(new BaseStudent("赵六",26));
		
		list1.addAll(list2);                       //可将子类的集合对象添加到父类集合中
		System.out.println(list1);
	}

}

class CompareByAge implements Comparator<Student> {

	@Override
	public int compare(Student s1, Student s2) {
		int num = s1.getAge() - s2.getAge();
		return num == 0 ? s1.getName().compareTo(s2.getName()) : num;
	} 
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值