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)+", ");
}
} }