1:map集合(掌握)
(1)Map集合存储的是键值对元素。键是唯一的,值可以重复。
(2)Map和Collection的区别?
A:Map是双列集合,存储的元素键值对,键唯一,值可以重复。
B:Collection是单列集合,存储的元素是单一的,List集合可以重复,Set集合元素唯一。
(3)Map集合的功能
A:添加功能
V put(K key,V value)
B:删除功能
remove(K key)
C:判断功能
containsKey(K key)
containsValue(V value)
D:获取功能
V get(K key)
Set<K> keySet()
Collection<V> values()
Set<Map.Entry<K,V>> entrySet() 返回所有键值对对应关系
Map.Entry是Map内的一个内部接,包含的主要方法
K getKey()
V getValue()
V setValue(V value) 设置值
E:长度功能
int size()
(4)Map集合的数据结构问题:
Map集合的数据结构对键有效,跟值无关。
它的底层数据结构和Set中讲解的一致。
如果是哈希表结构,就需要重写hashCode()和equals(),保证存储元素的唯一性。
如果是二叉树结构,就有两种方式:Comparable,Comparator,保证存储的元素的有序性。 例子程序如下:

mport java.util.Comparator; import java.util.TreeMap; /* * 使用TreeMap存储<Person,String> */ public class Demo7 { public static void main(String[] args) { //第一种方式:使键的类型实现Comparable接口,完成比较大小的逻辑 TreeMap<Person, String> map = new TreeMap<>(); Person p = new Person("唐嫣", 28); String s = "貂蝉"; Person p2 = new Person("卢俊义",42); String s2 = "玉麒麟"; Person p3 = new Person("2张顺",32); String s3 = "浪里白条"; Person p4 = new Person("1花荣",32); String s4 = "小李广"; map.put(p, s); map.put(p2, s2); map.put(p3, s3); map.put(p4, s4); System.out.println(map); //第二种方式:创建集合对象时给予对应的比较器Comparator TreeMap<Person, String> map2 = new TreeMap<>(new Comparator<Person>(){ @Override public int compare(Person o1, Person o2) { int result = o1.getName().compareTo(o2.getName()); if(result==0) { result = o1.getAge()-o2.getAge(); } return result; }}); map2.put(p, s); map2.put(p2, s2); map2.put(p3, s3); map2.put(p4, s4); System.out.println(map2); } }

public class Person implements Comparable<Person>{ private String name; private int age; public Person() { super(); // TODO Auto-generated constructor stub } public Person(String name, int age) { super(); this.name = name; this.age = age; } //先比较年龄,后比较姓名 @Override public int compareTo(Person o) { //this:新传进来的对象 o:旧的对象 int result = this.age-o.age; if(result==0) { result = this.name.compareTo(o.name); } return result; } @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; Person other = (Person) 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 "Person [name=" + name + ", 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; } }
(5)Map的遍历方式
假设有一个HashMap集合,存储的键和值都是String类型。名称叫hm。
A:根据键找值(掌握)
a:获取所有键的集合
b:遍历键的集合,获取到每一个键
c:根据键找值
代码体现:
Set<String> set = hm.keySet();
for(String key : set) {
String value = hm.get(key);
System.out.println(key+"---"+value);
}
B:根据键值对对象找键和值(理解)
a:获取所有键值对对象的集合
b:遍历键值对对象的集合,获取到每一个键值对对象
c:根据键值对对象获取键和值
代码体现:
Set<Map.Entry<String,String>> set = hm.entrySet();
for(Map.Entry<String,String> me : set) {
String key = me.getKey();
String value = me.getValue();
System.out.println(key+"---"+value);
}
(6)案例:
A:统计一个字符串中每个字符出现的次数

import java.util.Set; import java.util.TreeMap; /** * “aabcbdeeeeedbddcc”,获取字符串中每一个字母出现的次数。要求结果:a(2)b(3)c(3)d(4)e(5) * 思路:字符串中的字符和数字存到treemap集合里,然后遍历输出 */ public class MapTest1 { public static void main(String[] args) { // 定义一个字符串(可以改进为键盘录入) String content ="aababcabcdabcde"; // 定义一个TreeMap集合 TreeMap<Character, Integer> tm = new TreeMap<Character, Integer>(); //把字符串转换为字符数组 char[] chs = content.toCharArray(); //遍历字符数组,得到每一个字符 for(char ch : chs){ //拿刚才得到的字符作为键到集合中去找值,看返回值 Integer i = tm.get(ch); //是null:说明该键不存在,就把该字符作为键,1作为值存储 if(i == null){ tm.put(ch, 1); }else { //不是null:说明该键存在,就把值加1,然后重写存储该键和值 i++; tm.put(ch,i); } } //定义字符串缓冲区变量 StringBuilder sb= new StringBuilder(); //遍历集合,得到键和值,进行按照要求拼接 Set<Character> set = tm.keySet(); for(Character key : set){ Integer value = tm.get(key); sb.append(key).append("(").append(value).append(")"); } //把字符串缓冲区转换为字符串输出 String result = sb.toString(); System.out.println("result:"+result); } }
B:Map集合的嵌套存储和遍历

import java.util.ArrayList; import java.util.HashMap; import java.util.Set; /* * List集合内元素为Map集合 */ public class Test { public static void main(String[] args) { //List嵌套List //创建集合对象 ArrayList<ArrayList<String>> arrayList = new ArrayList<ArrayList<String>>(); //创建元素对象 ArrayList<String> list = new ArrayList<String>(); list.add("吕布"); list.add("赵云"); list.add("典韦"); list.add("关羽"); list.add("马超"); ArrayList<String> list2 = new ArrayList<String>(); list2.add("高俅"); list2.add("高衙内"); list2.add("蔡京"); list2.add("西门大官人"); //将集合元素放入集合对象 arrayList.add(list); arrayList.add(list2); System.out.println(arrayList); //List嵌套Map //创建集合对象 ArrayList<HashMap<String, Person>> arrayList2 = new ArrayList<HashMap<String, Person>>(); //创建元素对象 HashMap<String, Person> hashMap = new HashMap<String, Person>(); hashMap.put("五虎上将之一", new Person("关羽",38)); hashMap.put("五虎上将之二", new Person("张飞",34)); hashMap.put("五虎上将之三", new Person("赵云",32)); hashMap.put("五虎上将之四", new Person("马超",30)); hashMap.put("五虎上将之五", new Person("黄忠",60)); HashMap<String, Person> hashMap2 = new HashMap<String, Person>(); hashMap2.put("行者", new Person("武松",28)); hashMap2.put("神行太保", new Person("戴宗",34)); hashMap2.put("入云龙", new Person("公孙胜",32)); hashMap2.put("九纹龙", new Person("史进",30)); hashMap2.put("拼命三郎", new Person("石秀",29)); //将集合元素添加到集合中 arrayList2.add(hashMap); arrayList2.add(hashMap2); //迭代外层的ArrayList,里边的每个元素均为Map对象 for (HashMap<String, Person> myMap : arrayList2) { //HashMap<String, Person> myMap //返回该map的所有key的Set集合 Set<String> keySet = myMap.keySet(); for (String key : keySet) {//迭代key的集合,获取每一个key Person value = myMap.get(key); //通过键获取值 //拼写字符串,完成对每个map中元素的打印 System.out.println(key+":"+value.getName()+" "+value.getAge()); } } } }

import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; /* * 使用Map嵌套List */ public class Test2 { public static void main(String[] args) { //创建map集合 Map<String, ArrayList<Person>> map = new HashMap<String, ArrayList<Person>>(); //创建集合元素 String class1 = "0315基础班"; ArrayList<Person> arrayList = new ArrayList<Person>(); arrayList.add(new Person("唐嫣",28)); arrayList.add(new Person("龙哥",23)); arrayList.add(new Person("小龙女",16)); arrayList.add(new Person("涛哥",31)); String class2 = "0426就业班"; ArrayList<Person> arrayList2 = new ArrayList<Person>(); arrayList2.add(new Person("唐嫣",28)); arrayList2.add(new Person("高圆圆",32)); arrayList2.add(new Person("baby",26)); arrayList2.add(new Person("熊黛林",32)); //将集合元素添加到集合中 map.put(class1, arrayList); map.put(class2, arrayList2); //遍历map集合 Set<Entry<String,ArrayList<Person>>> entrySet = map.entrySet(); Iterator<Entry<String, ArrayList<Person>>> iterator = entrySet.iterator(); while (iterator.hasNext()) { Map.Entry<java.lang.String, java.util.ArrayList<cn.itcast2.Person>> entry = (Map.Entry<java.lang.String, java.util.ArrayList<cn.itcast2.Person>>) iterator .next(); String key = entry.getKey(); ArrayList<Person> listValue = entry.getValue(); System.out.println(key); Iterator<Person> iterator2 = listValue.iterator(); while (iterator2.hasNext()) { Person person = (Person) iterator2.next(); System.out.println(person); } } } }

import java.util.HashMap; import java.util.Map; import java.util.Set; /* * Map嵌套Map */ public class Test3 { public static void main(String[] args) { Map<String, Map<String, Person>> map = new HashMap<String, Map<String,Person>>(); Map<String, Person> innerMap = new HashMap<String, Person>(); innerMap.put("师傅", new Person("唐三藏",34)); innerMap.put("大师兄", new Person("孙悟空",500)); innerMap.put("二师兄", new Person("朱悟能",800)); innerMap.put("三师弟", new Person("沙悟净",600)); Map<String, Person> innerMap2 = new HashMap<String, Person>(); innerMap2.put("顽石", new Person("贾宝玉",14)); innerMap2.put("十二金钗之一", new Person("薛宝钗",19)); innerMap2.put("十二金钗之二", new Person("王熙凤",28)); map.put("西游记", innerMap); map.put("红楼梦", innerMap2); Set<String> keySet = map.keySet(); for (String key : keySet) { Map<String, Person> value = map.get(key); System.out.println(key); Set<String> keySet2 = value.keySet(); for (String innerKey : keySet2) { Person innerValuePerson = value.get(innerKey); System.out.println(innerKey+":"+innerValuePerson); } } } }
(7)Map集合的体系
Map
|--HashMap
|--LinkedHashMap
|--Hashtable
|--TreeMap
A:HashMap和Hashtable的区别?
HashMap键无序,不可重复,不安全,速度快,键和值都可以存放空值。
Hashtable键无序,不可重复,安全,速度慢,键和值都不可以存放空值。
B:LinkedHashMap的键的特点?
键有序,不可重复。
2:集合总结(什么时候使用谁?)
是否键值对:
是:Map
是否排序:
是:TreeMap
否:HashMap
不知道,HashMap
否:Collection
是否唯一:
是:Set
是否排序:
是:TreeSet
否:HashSet
不知道,HashSet
否:List
增删多:LinkedList
查询多:ArrayList
不知道,ArrayList
不知道,用ArrayList
3:集合体系总结
集合:
|--Collection
|--List
|--ArrayList
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高。
|--Vector
底层数据结构是数组,查询快,增删慢。
线程安全,效率低。
|--LinkedList
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高。
|--Set
|--HashSet
底层数据结构是哈希表。
如何保证唯一性?
依赖hashCode()和equals()
顺序:
先判断hashCode()值是否相同:
是:继续走equals(),看返回值
true:元素重复。不添加
false:元素不重复。添加
否:直接添加
|--LinkedHashSet
底层数据结构是链表和哈希表。
由链表保证有序(存储和取出一致)。
由哈希表保证元素唯一。
|--TreeSet
底层数据结构是二叉树。
如果保证唯一性?
根据返回值是否是0。
如何排序:
自然排序:Comparable
比较器排序:Comparator
|--Map
|--HashMap
|--LinkedHashMap
|--Hashtable
|--TreeMap
附:例子
1、Map嵌套Map的例子

import java.util.HashMap; import java.util.Set; /** * 使用集合进行以下分类: 北京总部 -JAVAEE班:5个 -JAVASE班:8个 上海分校 -JAVAEE:4个 -JAVASE:7个 */ public class Map3 { public static void main(String[] args) { //创建HashMap集合 HashMap<String,HashMap<String,String>> hashMap=new HashMap<String,HashMap<String,String>>(); //创建元素 HashMap<String,String> innerHashMap1=new HashMap<String,String>(); innerHashMap1.put("JavaEE班","5个"); innerHashMap1.put("JavaSE班","8个"); HashMap<String,String> innerHashMap2=new HashMap<String,String>(); innerHashMap2.put("JavaEE班","4个"); innerHashMap2.put("JavaSE班","7个"); //添加元素 hashMap.put("北京总部",innerHashMap1); hashMap.put("上海分校",innerHashMap2); //遍历输出 Set<String> keySet=hashMap.keySet(); //外层key集合 for(String key:keySet){ System.out.println(key); //输出外层key HashMap<String,String> innerHashMap= hashMap.get(key);//获取外层key对应的Value值 Set<String> inKeySet=innerHashMap.keySet();//内层key集合 for(String innerkey:inKeySet){ String innerValue=innerHashMap.get(innerkey); System.out.println(" "+innerkey+":"+innerValue);//输出内层key与内层Vakue } } } }
2、模拟地主洗牌发牌
方法一:

import java.util.ArrayList; import java.util.Collections; /* * 模拟斗地主洗牌发牌版本1 */ public class Test5 { public static void main(String[] args) { /*准备: * 花色:♠♥♦♣ ArrayList * 数字:3,4,5,6,7,8,9,10,J,Q,K,A,2 ArrayList * 大小王:☺☻ * 得有一副54张的牌 ArrayList * 洗牌: * 打乱这副牌的顺序 * 发牌: * 将54张牌分发到4个list手中,前三个17张,最后一个3张 * player ArrayList * player2 ArrayList * player3 ArrayList * dipai ArrayList */ //准备花色 ArrayList<String> color = new ArrayList<String>(); color.add("♠"); color.add("♥"); color.add("♦"); color.add("♣"); //准备数字 ArrayList<String> number = new ArrayList<String>(); Collections.addAll(number, "3","4","5","6","7","8","9","10","J","Q","K","A","2"); //准备一副新牌 ArrayList<String> cards = new ArrayList<String>(); for (String thisColor : color) { for (String thisNumber : number) { cards.add(thisColor+thisNumber); } } //加入大小王 cards.add("大☻"); cards.add("小☺"); System.out.println(cards); //洗牌 Collections.shuffle(cards); System.out.println(cards); //发牌 //准备四个list作为3个玩家和底牌 ArrayList<String> player = new ArrayList<String>(); ArrayList<String> player2 = new ArrayList<String>(); ArrayList<String> player3 = new ArrayList<String>(); ArrayList<String> dipai = new ArrayList<String>(); //遍历这副洗好的牌,遍历过程中,将牌发到三个玩家和dipai手中 for (int i = 0; i < cards.size(); i++) { if(i>=51) {//分配底牌 dipai.add(cards.get(i)); } else { if(i%3==0) { player.add(cards.get(i)); }else if(i%3==1) { player2.add(cards.get(i)); }else { player3.add(cards.get(i)); } } } //看牌 System.out.println(player); System.out.println(player2); System.out.println(player3); System.out.println(dipai); } }
方法二:

import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.TreeSet; /* * 斗地主洗牌发牌版本2:每个人手中的元素是有顺序的。 */ public class Test5 { /*准备: * 花色:♠♥♦♣ ArrayList * 数字:3,4,5,6,7,8,9,10,J,Q,K,A,2 ArrayList * 大小王:☺☻ * !!!!!!!!定义一个map集合:用来将数字与每一张牌进行对应 * 得有一副54张的牌 ArrayList里边为1-54的数 * 洗牌: * 打乱这副牌的顺序 * 发牌: * 将54张牌分发到4个TreeSet手中,前三个17张,最后一个3张 * player TreeSet * player2 TreeSet * player3 TreeSet * dipai TreeSet */ public static void main(String[] args) { //准备花色 ArrayList<String> color = new ArrayList<String>(); color.add("♠"); color.add("♥"); color.add("♦"); color.add("♣"); //准备数字 ArrayList<String> number = new ArrayList<String>(); Collections.addAll(number, "3","4","5","6","7","8","9","10","J","Q","K","A","2"); //定义一个map集合:用来将数字与每一张牌进行对应 HashMap<Integer, String> hashMap = new HashMap<Integer, String>(); int index = 1; for (String thisNumber : number) { for (String thisColor : color) { hashMap.put(index++, thisNumber+thisColor); } } //加入大小王 hashMap.put(index++, "小☺"); hashMap.put(index++, "大☻"); System.out.println(hashMap); //得有一副54张的牌 ArrayList里边为1-54的数的新牌 ArrayList<Integer> cards = new ArrayList<Integer>(); for (int i = 1; i <= 54; i++) { cards.add(i); } //洗牌 Collections.shuffle(cards); System.out.println(cards); //创建三个玩家和底牌 TreeSet<Integer> player = new TreeSet<Integer>(); TreeSet<Integer> player2 = new TreeSet<Integer>(); TreeSet<Integer> player3 = new TreeSet<Integer>(); TreeSet<Integer> dipai = new TreeSet<Integer>(); //遍历这副洗好的牌,遍历过程中,将牌发到三个玩家和dipai手中 for (int i = 0; i < cards.size(); i++) { if(i>=51) { dipai.add(cards.get(i)); } else { if(i%3==0) { player.add(cards.get(i)); }else if(i%3==1) { player2.add(cards.get(i)); }else { player3.add(cards.get(i)); } } } //看牌 for (Integer key : dipai) { System.out.print(hashMap.get(key)+", "); } System.out.println(); for (Integer key : player) { System.out.print(hashMap.get(key)+", "); } System.out.println(); for (Integer key : player2) { System.out.print(hashMap.get(key)+", "); } System.out.println(); for (Integer key : player3) { System.out.print(hashMap.get(key)+", "); } } }