知识点
Map集合基础,练习
-
Map存储数据的特点是什么?
Map集合的特点
-
键值对映射关系
-
一个键对应一个值
-
键不能重复,值可以重复
-
元素存取无序
-
-
描述HashMap的底层实现原理(jdk 8版)?
首先看数据结构,jdk8之前是数组加链表。Jdk8加入了红黑树。(为了避免链表过长产生循环链表)。 对于添加,同一个索引位置的节点超过8个(阈值8)并且数组长度大于或者等于64链表会转为红黑树,小于64会进行扩容。 对于删除,同样一个索引位置的节点在移除之后达到6个(阈值6),并且该索引位置的节点为红黑树节点。红黑树会转为链表 然后最核心的是put方法和get方法。
-
Map中常用实现类有哪些?各自有什么特点?
HashMap,TreeMap,Hashtable以及LinkedHashMap
HashMap:HashMap的值是没有顺序的,按照key的HashCode来实现的,就是根据key的HashCode 值来存储数据,根据key可以直接获取它的Value,同时它具有很快的访问速度。HashMap最多只允许一条记录的key值为Null(多条会覆盖);允许多条记录的Value为 Null。非同步的。
TreeMap: 能够把它保存的记录根据key排序,默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null。非同步的。
Hashtable: 与 HashMap类似,不同的是:key和value的值均不允许为null;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢,只有hashtable是继承自Dictionary抽象类的,hashMap和treeMap都继承自AbstractMap抽象类,LinkedHashMap继承自hashMap。
LinkedHashMap: 保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.在遍历的时候会比HashMap慢。key和value均允许为空,非同步的。
-
如何遍历Map中的key-value对,代码实现(至少2种)
//获取所有键值对对象的集合 Set<Map.Entry<String, String>> entrySet = map.entrySet(); //遍历键值对对象的集合,得到每一个键值对对象 for (Map.Entry me : entrySet) { //根据键值对对象获取键和值 String key = me.getKey(); String value = me.getValue(); System.out.println(key + "," + value); }
//2、先用keySet()取出所有key值,再取出对应value——增强for循环遍历*/ Set keyset = hashMap.keySet(); for(Object key:keyset){ System.out.println(key+"-"+hashMap.get(key)); }
-
Collection和Collections的区别?
Collection集合接口
Collections集合工具类
-
Map接口中的常用方法有哪些 ?
V put(K key,V value) 添加元素 V remove(Object key) 根据键删除键值对元素 void clear() 移除所有的键值对元素 boolean containsKey(Object key) 判断集合是否包含指定的键 boolean containsValue(Object value) 判断集合是否包含指定的值 boolean isEmpty() 判断集合是否为空 int size() 集合的长度,也就是集合中键值对的个数 V get(Object key) 根据键获取值 Set<K> keySet() 获取所有键的集合 Collection<V> values() 获取所有值的集合 Set<Map.Entry<K,V>> entrySet() 获取所有键值对对象的集合 -
(Map)已知某学校的教学课程内容安排如下: 前者是老师,后者是老师所教的课程: ("Tom", "CoreJava"); ("John", "Oracle"); ("Susan", "Oracle"); ("Jerry", "JDBC"); ("Jim", "Unix"); ("Kevin", "JSP"); ("Lucy", "JSP"); 完成下列要求: 1) 使用一个Map,以老师的名字作为键,以老师教授的课程名作为值,表示上述课程安排。 2) 增加了一位新老师Allen 教JDBC 3) Lucy 改为教CoreJava 4) 遍历Map,输出所有的老师及老师教授的课程(用Set<Map.Entry<String,String>>、Set<String> get(key)都可) 5) 利用Map,输出所有教JSP的老师。
import java.util.*; public class Demo1 { public static void main(String[] args) { //创建集合对象 Map <String ,String> map=new HashMap<>(); //添加元素 map.put("Tom", "CoreJava"); map.put("John", "Oracle"); map.put("Susan", "Oracle"); map.put("Jerry", "JDBC"); map.put("Jim", "Unix"); map.put("Kevin", "JSP"); map.put("Lucy", "JSP"); //增加了一位新老师Allen 教JDBC map.put("Allen", "JDBC"); //Lucy 改为教CoreJava map.replace("Lucy", "JSP","CoreJava"); //遍历 //获取所有键值对对象的集合 Set<Map.Entry<String, String>> entrySet = map.entrySet(); // 遍历键值对对象的集合,得到每一个键值对对象 for (Map.Entry me : entrySet) { //根据键值对对象获取键和值 System.out.println(me.getKey() + "," + me.getValue()); } //利用Map,输出所有教JSP的老师。 getKey(map,"JSP"); } /** * 根据map的value获取map的key * 注意:value相同的值有很多个,都会对应到第一个找到的key上,因此要把找到的key标记,下次不再用 */ private static void getKey(Map<String,String> map, String value){ String key=""; //遍历map for (Map.Entry<String, String> entry : map.entrySet()) { //如果value和key对应的value相同 并且 key不在list中 if(entry.getValue().equals(value)){ key=entry.getKey(); System.out.println(key); } } } }
-
模拟斗地主洗牌发牌(争取根据自己的思路在写一遍) /* 1、分析:首先应准备牌:完成数字与纸牌的映射关系:使用双列Map(HashMap)集合,完成一个数字与字符串纸牌的对应关系。 洗牌:通过数字完成洗牌发牌(借助工具类) 发牌:将每个人以及底牌设计,将最后3张牌直接存放于底牌,剩余牌通过对3取模依次发牌给3个玩家。存放的过程中要求数字大小与斗地主规则的大小对应排序。将代表不同纸牌的数字分配给不同的玩家与底牌。 看牌:通过Map集合找到对应字符展示。通过查询纸牌与数字的对应关系,由数字转成纸牌字符串再进行展示。*/
import java.util.*; public class Demo1 { public static void main(String[] args) { //备牌 :首先应准备牌:完成数字与纸牌的映射关系:使用双列Map(HashMap)集合,完成一个数字与字符串纸牌的对应关系。 // 创建对象,HashMap的key是编号,Value是牌 HashMap<Integer, String> map = new HashMap<Integer, String>(); //储存编号 ArrayList<Integer> list = new ArrayList<>(); //添加花色和数字数组 String[] colors = {"♥", "♠", "♦", "♣"}; String[] numbers = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "K", "Q", "J", "A"}; // 从0开始往HashMap里面存储编号,并存储对应的牌。同时往ArrayList里面存储编号 int index = 0; // 双循环,外循环是花色,内循环是数字 for (String color : colors) { for (String number : numbers) { map.put(index, color + number);//往HashMap里面存储编号,并存储对应的牌 list.add(index);//往ArrayList里面存储编号 index++;//编号自增 } } //导入大小王,存入编号 map .put(index, "大王"); list.add(index); index++;//编号自增 map.put(index, "小王"); list.add(index); //洗牌(洗的是编号index),打乱已有顺序Collections.shuffle(); Collections.shuffle(list); //发牌:将每个人以及底牌设计,将最后3张牌直接存放于底牌,剩余牌通过对3取模依次发牌给3个玩家。存放的过程中要求数字大小与斗地主规则的大小对应排序。将代表不同纸牌的数字分配给不同的玩家与底牌。 //创建TreeSet集合(支持排序)接收排序的牌(编号) TreeSet<Integer> aSet = new TreeSet<Integer>(); TreeSet<Integer> bSet = new TreeSet<Integer>(); TreeSet<Integer> cSet = new TreeSet<Integer>(); TreeSet<Integer> dpSet = new TreeSet<Integer>();//底牌 //遍历发牌 for (int i = 0; i < list.size(); i++) {//循环最多执行54次 int x = list.get(i); if (i >= list.size() - 3) {//大于51即只剩最后3张牌 dpSet.add(x);//最后三张牌给到底牌 } else if (i % 3 == 0) { aSet.add(x);//编号对3取余,若余数为0给到玩家a } else if (i % 3 == 1) { bSet.add(x);//编号对3取余,若余数为1给到玩家b } else if (i % 3 == 2) { cSet.add(x);//编号对3取余,若余数为2给到玩家c } } // 看牌:通过Map集合找到对应字符展示。通过查询纸牌与数字的对应关系,由数字转成纸牌字符串再进行展示。 //先定义一个方法,调用方法 //调用看牌方法showMap() showMap("玩家A", aSet, map); showMap("玩家B", bSet, map); showMap("玩家C", cSet, map); showMap("底牌", dpSet, map); } public static void showMap (String name, TreeSet < Integer > ts, HashMap< Integer, String > map){ System.out.print(name+"的牌是:");//不分行 for (Integer key : ts) { String y = map.get(key); System.out.print(y+" ");//不分行 } System.out.println();//间隔 } }
-
【1】将以下车站对应关系的数据存储到map集合中, key:表示站编号,value:表示站名, 并遍历打印(可以不按顺序打印): ------------------------------------ 站编号和站名对应关系如下: 1 朱辛庄 2 育知路 3 平西府 4 回龙观东大街 5 霍营 6 育新 7 西小口 8 永泰庄 9 林萃桥 10 森林公园南门 11 奥林匹克公园 12 奥体中心 13 北土城 14 安华桥 15 安德里北街 16 鼓楼大街 17 什刹海 18 南锣鼓巷 19 中国美术馆 ------------------------------------ 【2】计算地铁票价规则: 总行程 3站内(包含3站)收费3元, 3站以上但不超过5站(包含5站)的收费4元, 5站以上的,在4元的基础上,每多1站增加2元, 10元封顶; 需要对键盘录入的上车站 和到达站进行判断,如果没有该站, 提示重新输入,直到站名存在为止 每站需要2分钟 示范如下: ------------------------------------- 请输入上车站: 流沙河 您输入的上车站:流沙河站不存在,请重新输入上车站: 骑龙 您输入的上车站:骑龙站不存在,请重新输入上车站: 朱辛庄 您以确定在朱辛庄上站! 请输入到达站: 沙河 您输入的到达站:沙河站不存在,请重新输入到达站: 西二旗 您输入的到达站:西二旗站不存在,请重新输入到达站: 西小口 您以确定在朱辛庄下站! 从朱辛庄到西小口共经过6站收费6元,大约需要12分钟 -----------------------------------------------
import java.util.*; public class Demo1 { public static void main(String[] args) { //将以下车站对应关系的数据存储到map集合中, //key:表示站编号,value:表示站名,并遍历打印(可以不按顺序打印): Map<Integer,String> map = new HashMap<>(); map.put(1,"朱辛庄");map.put(2,"育知路");map.put(3,"平西府");map.put(4,"回龙观东大街");map.put(5,"霍营");map.put(6,"育新"); map.put(7,"西小口");map.put(8,"永泰庄");map.put(9,"林萃桥");map.put(10,"森林公园南门");map.put(11,"奥林匹克公园");map.put(12,"奥体中心"); map.put(13,"北土城");map.put(14,"安华桥");map.put(15,"安德里北街");map.put(16,"鼓楼大街");map.put(17,"什刹海");map.put(18,"南锣鼓巷");map.put(19,"中国美术馆"); //并遍历打印(可以不按顺序打印) //获取所有键值对对象的集合 Set<Map.Entry<Integer, String>> entrySet = map.entrySet(); // 遍历键值对对象的集合,得到每一个键值对对象 for (Map.Entry me : entrySet) { //根据键值对对象获取键和值 System.out.println(me.getKey() + "," + me.getValue()); } boolean flag = true; while (flag) { //------------------------------------- //请输入上车站: int stair = 0, stair1 = 0; System.out.println("_______________________________"); System.out.println("请输入上车站:"); Scanner sc = new Scanner(System.in); String a = sc.next(); // Set keyset = map.keySet(); //如果value和key对应的value相同 并且 key不在list中 if (getKey(map, a)) { stair=stair(map,a); System.out.println("您已确定在" + a + "上站!!!"); boolean flag1=true; while (flag1) { System.out.println("请输入到达站:"); String b = sc.next(); if (getKey(map, b)) { stair1= stair(map,b); int money = 0; System.out.println("您已确定在" + b+ "下车!!!"); int c = 0; if ((int) stair1 - (int) stair >= 0) { c = (int) stair1 - (int) stair; } else { c = -((int) stair1 - (int) stair); } if ((int) stair1 - (int) stair <= 3) { money = 3; } else if ((int) stair1 - (int) stair <= 5) { money = 4; } else if ((int) stair1 - (int) stair > 5) { money = 4 + c; if (money > 10) { money = 10; } } System.out.println("从朱辛庄到西小口共经过" + c + "站收费" + money + "元,大约需要" + 2 * c + "分钟"); System.out.println("--------------------------------------------------------------"); flag1 = false; flag=false; }else { System.out.println("您输入的到达站:" + b + "不存在,请重新输入到达站:"); } } }else{ System.out.println("您输入的上车站:" + a + "不存在,请重新输入上车站:"); } } } private static boolean getKey(Map<Integer,String> map, String value) { int key = 0; //遍历map for (Map.Entry<Integer, String> entry : map.entrySet()) { //如果value和key对应的value相同 并且 key不在list中 if (entry.getValue().equals(value)) { key = entry.getKey(); } }return map.containsKey(key); } private static int stair(Map<Integer,String> map, String value) { int stair = 0; //遍历map for (Map.Entry<Integer, String> entry : map.entrySet()) { //如果value和key对应的value相同 并且 key不在list中 if (entry.getValue().equals(value)) { stair = entry.getKey(); } }return stair; } }