在实际需求中,我们常常会遇到这样的问题,在诸多的数据中,通过其编号来寻找某一些信息,从而进行查看或者修改,例如通过学号查询学生信息。今天我们所介绍的Map集合就可以很好的帮助我们实现这种需求
Map是一种存储元素对的集合(元素对分别称作 键 和 值 也称键值对)它将键映射到值的对象。一个映射不能包含重复的键,并且每个键最 多只能映射到一个值。
怎么理解呢?
键 (key):就是你存的值的编号 值 (value):就是你要存放的数据
你可以近似的将键理解为下标,值依据键而存储,每个键都有其对应值。这两者是1、1对应的
但在之前下标是整数,但是Map中键可以使任意类型的对象。
//添加元素 V put(K key,V value) //如果键是第一次存储,就直接存储元素,返回null //如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
//移除所有的键值对元素 void clear() //根据键删除键值对元素,并把值返回 V remove(Object key)
//判断集合是否包含指定的键 boolean containsKey(Object key) //判断集合是否包含指定的值 boolean containsValue(Object value) //判断集合是否为空 boolean isEmpty()
//将map集合中的键和值映射关系打包为一个对象 Set<Map.Entry<K,V>> entrySet() //根据键获取值 V get(Object key) //获取集合中所有键的集合 Set<K> keySet() //获取集合中所有值的集合 Collection<V> values()
//返回集合中的键值对的对数 int size()
package cn.bwh_01_iterator; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class MapDemo { public static void main(String[] args) { Map<String, String> hm = new HashMap<String, String>(); hm.put("bwh002", "i"); hm.put("bwh001", "love"); hm.put("bwh003", "you"); //方式一 键找值 Set<String> set = hm.keySet(); //迭代器遍历 Iterator<String> it = set.iterator(); while (it.hasNext()) { String key = it.next(); String value = hm.get(key); System.out.println(key + "---" + value); } //增强for遍历 for (String key : set) { String value = hm.get(key); System.out.println(key + "---" + value); } //方式二 键值对对象找键和值(推荐) Set<Map.Entry<String, String>> set2 = hm.entrySet(); //迭代器遍历 Iterator<Map.Entry<String, String>> it2 = set2.iterator(); while (it2.hasNext()) { //返回的是封装了key和value对象的Map.Entry对象 Map.Entry<String, String> entry = it2.next(); String key = entry.getKey(); String value = entry.getValue(); System.out.println(key + "---" + value); } //增强for遍历 for (Map.Entry<String, String> me : set2) { String key = me.getKey(); String value = me.getValue(); System.out.println(key + "---" + value); } } }
执行顺序:
首先判断hashCode()值是否相同
是:继续执行equals(),看其返回值
自然排序(元素具备比较性)
比较器排序(集合具备比较性)
HashMap集合嵌套HashMap
HashMap集合嵌套ArrayList
ArrayList集合嵌套HashMap
HashMap<String, ArrayList<String>> hm = new HashMap<String, ArrayList<String>>
**Hashtable**:线程安全,效率低。不允许null键和null值 **HashMap**:线程不安全,效率高。允许null键和null值
(其实HashMap就是用来替代Hashtable的,就像ArrayList替代vector一样)
List,Set不是继承自Map接口,它们继承自Collection接口
Map接口本身就是一个顶层接口
需要排序:TreeMap
不需要排序:HashMap
不知道具体需求:HashMap
import java.util.Map; import java.util.Scanner; import java.util.Set; import java.util.TreeMap; /* * 案例(统计字符串中字符出现的次数) * 需求: * 获取一个字符串出现的次数 * 分析: * A:定义一个字符串(或者键盘录入) * B: 定义一个TreeMap集合 * 键:Character * 值:Integer * C:把字符串转换为字符数组 * D: 遍历字符数组,得到每一个字符 * E: 拿刚才得到的字符作为键去集合中找,看返回值 * 是 null:说明该键不存在,就把该字符串作为键,1作为值去存储 * 不是 null:说明该键存在,就把值加 1 然后重写存储该键和值 * F: 定义字符串缓冲区变量 * G:遍历集合,得到该建和值,按照要求拼接 * H:最后把字符串缓冲区转换为字符串输出 */ public class CountDemo { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入需要统计的数据"); String line = sc.nextLine(); Map<Character, Integer> tm = new TreeMap<Character, Integer>(); char[] chs = line.toCharArray(); for (char ch : chs) { Integer i = tm.get(ch); if (i == null) { tm.put(ch, 1); } else { i++; tm.put(ch, i); } } StringBuilder s = new StringBuilder(); Set<Character> set = tm.keySet(); for (Character key : set) { Integer value = tm.get(key); s.append(key).append("(").append(value).append(")" + " "); } String result = s.toString(); System.out.println("result: " + result); } } //运行结果 请输入需要统计的数据 HelloWorld result: H(1) W(1) d(1) e(1) l(3) o(2) r(1)
在讲解这个案例之前,我们先来了解一个我们下面案例中所需要知道的知识点
Collections:是针对集合进行操作的工具类,都是静态方法。
Collection和Collections的区别?
Collection:是单列集合的顶层接口,有子接口List和Set。(Map是双列的)
Collections:是针对集合操作的工具类,有对集合进行排序和二分查找的方法
//排序 默认情况下是自然顺序。 public static <T> void sort(List<T> list) //二分查找 public static <T> int binarySearch(List<?> list,T key) //最大值 public static <T> T max(Collection<?> coll) //反转(逆序排序) public static void reverse(List<?> list) //随机置换(犹如洗牌,每次运行结果不一样) public static void shuffle(List<?> list) 如果同时有自然排序和比较器排序,以比较器排序为主(也就是说,当同时实现了Student类的自然排序(implements Comparable<Student>)以及比较器排序的话(new Comparator<Student>()),比较器排序会覆盖自然排序)
//斗地主案例代码 package cn.bwh_03_PokerGame; import java.util.*; public class PokerGame { public static void main(String[] args) { HashMap<Integer, String> hm = new HashMap<Integer, String>(); ArrayList<Integer> array = new ArrayList<Integer>(); String[] colors = {"♥", "♠", "♣", "♦"}; String[] numbers = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"}; int index = 0; for (String number : numbers) { for (String color : colors) { String poker = color.concat(number); hm.put(index, poker); array.add(index); index++; } } hm.put(index, "小王"); array.add(index); index++; hm.put(index, "大王"); array.add(index); index++; //洗牌 Collections.shuffle(array); //发牌(发的是编号,为了保证编号是排序的,使用TreeSet接收) TreeSet<Integer> player1 = new TreeSet<Integer>(); TreeSet<Integer> player2 = new TreeSet<Integer>(); TreeSet<Integer> player3 = new TreeSet<Integer>(); TreeSet<Integer> handcards = new TreeSet<Integer>(); for (int x = 0; x < array.size(); x++) { if (x >= array.size() - 3) { handcards.add(array.get(x)); } else if (x % 3 == 0) { player1.add(array.get(x)); } else if (x % 3 == 1) { player2.add(array.get(x)); } else if (x % 3 == 2) { player3.add(array.get(x)); } } System.out.println("---------------------欢乐斗地主----------------------"); //看牌(遍历TreeSet集合,获取编号,到HashMap集合找对应的牌) lookpocker("player1", player1, hm); lookpocker("player2", player2, hm); lookpocker("player3", player3, hm); lookpocker("预留", handcards, hm); } //看牌功能实现 public static void lookpocker(String name, TreeSet<Integer> ts, HashMap<Integer, String> hm) { System.out.println(name + "的牌是:"); for (Integer key : ts) { String value = hm.get(key); System.out.print(value + " "); } System.out.println(); } }
如果内容中有什么不足,或者错误的地方,欢迎大家给我留言提出意见, 蟹蟹大家 !^_^
如果能帮到你的话,那就来关注我吧!(系列文章均会在公众号第一时间更新)
一个坚持推送原创Java技术的公众号:理想二旬不止