Map集合:存在键值关系的集合,称为Map集合
之前谈到的Set,Collection集合他是一个单列的集合,你可以根据某一个对象的属性来找出某个想要的元素,那么今天所说的Map集合他是一个双列集合,有键和值(Map<K,V> K是映射键的类型,V是映射值的类型)。Map集合的数据结果都只和键有关,好,今天看看他的三个已知实现类:HashMap,LinkendHashMap和TreeMap。
HashMap:HashMap他是基于哈希表的Map接口的实现。他提供所有可选dede 映射操作,并且允许使用null值de和null键。(除了不同步和允许使用null值之外,HashMap类与Hashtable大致相同,此类不保证映射的顺序,就是说打印出来的结果不一定是按写的顺序排列的。)
当创建HashMap集合之后,用put方法添加元素时,第一次添加的键和值之后,返回一个数据类型,打印这个数据类型时,输出的是一个null,系统默认这对键值对是第一次赋值,当键值不变时,把值换成另外一个值,这是在打印这个数据类型时,仍然是打印出第一次赋值的值,但是最后打印这个集合时,输出的是第二次赋值的键值对,这里存在一个键相同值覆盖的问题(因为一个键只能映射一个值)。好,下来我们举例说明下,
先创建一个HashMap集合;
Map<String,String> hashMap=new HashMap<String,String>();
String put=hashMap.put("赵雷",“成都”);
System.out.println(put); //此时输出的值是null;
String put2=hashMap.put("赵雷","吉姆餐厅"); //此时是键不变,值换掉了
System.out.println(put2); //此时输出的值是“成都”,这个是根据键找值,当键相同时,返回的是上一次的值
hashMap.put("赵雷","南方姑娘");
hashMap.put("宋冬野","安河桥");
hashMap.put("朴树","平凡之路");
System.println(hashMap);
控制台输出:
null
成都
{宋冬野--安河桥,赵雷--南方姑娘,赵雷--吉姆餐厅,朴树--平凡之路 }元素的排列顺序是无序的,(输出的集合里,吉姆餐厅替换掉了成都,是因为一个键只能映射一个值,即键相同值覆盖)
当然,每一个集合都有一些功能,HashMap也不例外:
void clear():清除所有映射关系,即所有的键值对;
public V remove():集合中移除一对键值对
判断功能:
boolean containsKey(Object key):判断是否存在某个键
boolean containsValue(Object value):判断是否存在某个值
boolean isEmpty:判断是否为空。
好,以上我们来举例说明:
Map<Integer,String> hashMap=new HashMap<Integer,String>(); //泛型里边只能是引用数据类型
hashMap.put(1,"赵雷");
hashMap.put(2,"朴树");
hashMap.put(3,"张卫健");
hashMap.put(4,"黄海波");
hashMap.clear(); //调用clear功能将清除所有的键值对
hashMap.remove(1);
System.out.println(hashMap);//只需要输入键值,便会删除掉这个键值对。
键找值:
Map<String,String> hashMap=new HashMap<String,String>();
hashMap.put("路遥","平凡的世界");
hashMap.put("刘同","你的孤独,虽败犹荣");
hashMap.put("曹文轩","草房子");
hashMap.put("莫言","四十一炮");
String str=hashMap.get("刘同");
System.out.println(str); //此时,”刘同“对应的值应该是“你的孤独,虽败犹荣”
获取所有的值:
Collection<String> value=hashMap.values();
for(String str2:value){
System.out.println(str2);
}
值找键(获取所有的键):
Set<String> key=hashMap.keySet();
for(String str3:key){
System.out.println(str3);
}
//再加上一句获得集合元素长度
System.out.println(hashMap.size());
下来再来看个例子:
public class HashMapDemo{
public static void main(String[] args){
Map<String,String> hashMap= new HashMap<String,String>();
hashMap.put("朴树","那些花儿");
hashMap.put("赵雷","南方姑娘"); //HashMap允许插入null值null键
hashMap.put("张卫健","疼爱");
hashMap.put("胡夏","那些年");
现在来遍历集合:(方式一)
Set<String> key=hashMap.keySet();
for(String str: key){
String value=str.get(key);
System.out.println(key+"----"+value);
}
遍历集合:(方式二:键值对 对象)
Set<Map.Entry<String,String>> entry=hashMap.entrySet();
for(Map.Entry<String,String> entries:entry){
String key= entries.getKey();
String value=entries.getValue();
}
System.out.println(key+"---"+value);
}
}
问题一:下来我们看一下给一个自定义类,该如何去遍历集合呢?(键是String 值是Student类)
写一个标准学生类
public class Student{
private String name;
private int age;
public Student(){}
public Student(Stringf name,int age){
this.name=name;
this.age=age;
}
public String getName(){
return name;
}
public void setNme(String name){
this.name=name;
}
public int getAge(){
rerurn age;
}
public void setAge(int age){
this.age=age;
}
@Override
public String toString(){
return "Student [ name="+name+", age="+age+"]"
}
}
public class HashMapDemo{
public static void main(String[] args){
Map<String,Student> hashMap=new HashMap<String,Student>();
hashMap.put("a0001",new Student(陈小帅",21));
hashMap.put("a0001",new Student(吴大能",23));
hashMap.put("a0001",new Student(滑小稽",24));
hashMap.put("a0001",new Student(熊本熊",22));
Set<String> string=hashMap.keySet(); //方式一:keySet,get方法遍历
for(String str:string){
Student student= hashMap.get(str);
System.out.println(str+"---"+student.getName()+"---"+student.getAge());
}
方式二:entrySet来遍历
Set<Map.Entry<String,Student>>entry=hashMap.entrySet<String,Student>();
for(Map.Entry<String,Student> entrys:entry){
String key=entrys.getKey();
String value=entrys.getValue();
System.out.println(key+"---"+value,getName()+"---"+value.getAge());
}
}
}
问题二:接下来我们给同一个自定义类,(键是Student类 值是String类)该如何去遍历集合呢?
(此处同样使用问题一中的标准学生类)
public class HashMapDemo2{
public static void mian(String[] args){
Map<Student,String>hashMap=new HashMap<Student,String>();
hashMap.put(new Student(陈小帅",21),"a0001");
hashMap.put(new Student(吴大能",23),"a0001");
hashMap.put(new Student(滑小稽",24),"a0001");
hashMap.put(new Student(熊本熊",22),"a0001");
Set<Student> student=hashMap.keySet(); //方式一: keySet,get
for(Student students:student){
String value=hashMap.get(students);
System.out.println(students.getName()+"---"+students.getAge()+"---"+value);
}
方式二: entrySet
Set<Map.Entry<Student,String>> entry=hashMap.entrySet<Student,String>();
for(Map.Entry<Student,String> entrys:entry){
Student student=entrys.getKey();
String value=entrys.getValue();
System.out.println(student.getName()+"---"+student.getAge()+"---"+value);
}
}
}
LinkedHashMap:
Map的哈希表和链表的列表实现,具有可知的迭代顺序(即迭代顺序和赋值的顺序有关,正向或者逆向迭代)
LinkedHashMap的底层数据结构是哈希表和链表,元素有序且唯一,有序由链表保证,唯一由哈希表保证,线程数据不安全,执行效率高,Map集合的值只和键有关
好下来我们来看一个具体的例子:
LinkedHashMap<Integer,String> hashMap=new LinkedHashMap<Integer,String>();
hashMap.put(2,"赵雷");
hashMap.put(1,"朴树");
hashMap.put(4,"张卫健");
hashMap.put(3,"高圆圆");
Set<Integer> keys=hashMap.keySet();
for(Integer key:keys){
String value= hashMap.get(key);
System.out.println(key+"---"+value);
}
TreeMap:
底层数据结构是二叉树,元素唯一且排序。排序分为自然排序和比较器排序。以下也是用两个具体的例子来说明一下
方式一:自然排序
先建一个标准教师类,
public class Teacher implements Comparable<Teacher>{
private String name;
private int age;
public Teacher() {
super();
}
public Teacher(String name, int age) {
super();
this.name = name;
this.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;
}
@Override
public String toString() {
return "Teacher [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Teacher s) {
int r=this.age-s.age;
int r2=r==0? this.name.length()-s.name.length():r; //加黑部分下边会有说明
return r2;
}
}
public class TreeMapDemo {
public static void main(String[] args) {
TreeMap<Teacher, String> treeMap = new TreeMap<>();
treeMap.put(new Teacher("陈老师",18),"t001"); //如果没有实现Comparable接口,没有重写CompareTo方法,此处会有空指针异常,所以必须实现Comparable接口,必须重写ComparaTo方法,根据返回值来决定排列顺序
treeMap.put(new Teacher("张老师", 19), "t001");
treeMap.put(new Teacher("王老师", 30), "t001");
treeMap.put(new Teacher("李老师", 20), null);//可以插入null,treeMap.put(null,"t009"); 不允许插入null键
Set<Map.Entry<Teacher, String>> entries = treeMap.entrySet();
for(Map.Entry<Teacher, String> entry:entries){
Teacher key = entry.getKey();
String value = entry.getValue();
System.out.println(key.getName()+"---"+key.getAge()+"---"+value);
}
}
}
方式二:比较器排序
建立一个学生类
public class Student {
private String name;
private int age;
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.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;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
测试学生类,遍历集合。
public class TreeMapDemo2 {
public static void main(String[] args) {
TreeMap<Student3, String> treeMap = new TreeMap<>(new Comparator<Student3>(){
@Override
public int compare(Student3 s1, Student3 s2) {
int r=s1.getName().length()-s2.getName().length();
int r2=r==0? s1.getAge()-s2.getAge():r;
return r2;
}
});
treeMap.put(new Student3(" 陈小帅", 18),"c9527");
treeMap.put(new Student3(" 滑小稽", 34),"a2221");
treeMap.put(new Student3(" 大熊猫", 25),"b0001");
treeMap.put(new Student3(" 张卫健", 28),"e8888");
Set<Entry<Student3, String>> entrys=treeMap.entrySet();
for(Entry<Student3, String> entry:entrys) {
Student3 key = entry.getKey();
String value = entry.getValue();
System.out.println(key.getName()+"---"+key.getAge()+"---"+value);
}
}
}
下来再来看一下集合的嵌套,很重要,但是我觉得也很难,暂时的难只是时间问题,男人没有解决不了的事情
基础班
张三 20
李四 22
就业班
王五 21
赵六 23
代码实现下:
public class HashMapDemo2 {
public static void main(String[] args) {
HashMap<String, Integer> hashMap = new HashMap<>();
hashMap.put("张三", 20);
hashMap.put("李四", 22);
HashMap<String, Integer> hashMap2 = new HashMap<>();
hashMap2.put("王五", 21);
hashMap2.put("赵六", 23);
HashMap<String, HashMap<String, Integer>> hashMap3 = new HashMap<>();
hashMap3.put("基础班", hashMap);
hashMap3.put("就业班", hashMap2);
Set<String> keys = hashMap3.keySet();
for (String key : keys) {
System.out.println(key);
HashMap<String, Integer> map = hashMap3.get(key);
Set<String> keySet = map.keySet();
for (String values : keySet) {
Integer value = map.get(values);
System.out.println("\t" + key + "-----" + value);
}
System.out.println();
}
}
}
再开看一看如何统计一个字符串中每个字符出现的次数
public class MyMapDemo {
public static void main(String[] args) {
HashMap<Character, Integer> map = new HashMap<>();
Scanner sc = new Scanner(System.in);
System.out.println("请随便输入一段字符串");
String line = sc.next();
//我怎么来统计字符出现的次数呢?统计完之后,把键值关系的数据存到集合中
for (int i = 0; i < line.length(); i++) {
//获取单个字符
char key = line.charAt(i);
//abfefdadfefdaeaaaddd
if (map.get(key) == null) {
map.put(key, 1);
} else {
Integer value = map.get(key);
value++;
map.put(key, value);
}
}
// System.out.println(map);a(5) b(4) c(3) d(2) e(1)
//遍历集合拼串
StringBuffer sb = new StringBuffer();
Set<Character> characters = map.keySet();
for (Character ch : characters) {
sb.append(ch).append("(").append(map.get(ch)).append(")");
}
String s = sb.toString();
System.out.println("你要的结果" + s);
}
}
Map嵌套List集合:
public class MyMapDemo3 {
public static void main(String[] args) {
三国演义
吕布
周瑜
笑傲江湖
令狐冲
林平之
神雕侠侣
郭靖
杨过
把上面这组数据存起来 HashMap 嵌套List
ArrayList<String> sgyy = new ArrayList<>();
sgyy.add("吕布");
sgyy.add("周瑜");
ArrayList<String> xajh = new ArrayList<>();
xajh.add("令狐冲");
xajh.add("林平之");
ArrayList<String> sjxl = new ArrayList<>();
sjxl.add("郭靖");
sjxl.add("杨过"); HashMap<String, ArrayList<String>> hm = new HashMap<>();
hm.put("笑傲江湖", xajh);
hm.put("神雕侠侣", sjxl);
hm.put("三国演义", sgyy);
//遍历
Set<Map.Entry<String, ArrayList<String>>> entries = hm.entrySet();
for (Map.Entry<String, ArrayList<String>> en : entries) {
String key = en.getKey();
System.out.println(key);
ArrayList<String> value = en.getValue();
for (String k : value) {
System.out.println("\t"+k);
}
System.out.println();
}
}
}
List集合嵌套Map集合
public class MyMapDemo4 {
public static void main(String[] args) {
周瑜-- - 小乔
吕布-- - 貂蝉
郭靖-- - 黄蓉
杨过-- - 小龙女
令狐冲-- - 任盈盈
林平之-- - 岳灵珊
Map<String, String> sgyy = new HashMap<>();
sgyy.put("周瑜", "小乔");
sgyy.put("吕布", "貂蝉"); Map<String, String> sdxl = new HashMap<>();
sdxl.put("郭靖", "黄蓉");
sdxl.put("杨过", "小龙女"); Map<String, String> xajh = new HashMap<>();
sdxl.put("令狐冲", "任盈盈");
sdxl.put("林平之", "岳灵珊");
ArrayList<Map<String, String>> maps = new ArrayList<>();
maps.add(sgyy);
maps.add(sdxl);
maps.add(xajh);
//遍历
for (Map<String, String> map : maps) {
Set<String> strings = map.keySet();
for (String key : strings) {
System.out.println(key + "===" + map.get(key));
}
}
}
}
在学习数组的时候数组有数组工具类Arrays。那么集合有没有集合工具类呢? 有呢:Collections
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):随机置换
说了那么多,再来个干货游戏吧,哈哈(不过现在水平有限,没有学到页面化,只能是程序表示)
public class 斗地主 {
@SuppressWarnings("unused")
public static void main(String[] args) {
//创建一个索引集合
// TreeMap<Integer,String> treeMap = new TreeMap<Integer,String>();
HashMap<Integer,String> hashMap = new HashMap<Integer,String>();
ArrayList<Integer> arrayList = new ArrayList<Integer>();
String[] color= {"♥","♤","♣","♢"};
String[] num= {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
int index=0;
for(String nums:num) {
for(String colors:color) {
hashMap.put(index, colors.concat(nums));
arrayList.add(index);
index++;
}
}
//手动加上大小王。
// System.out.println(index);
hashMap.put(index,"☼");
arrayList.add(index);
index++;
hashMap.put(index,"小王");
arrayList.add(index);
//洗牌
Collections.shuffle(arrayList);
Collections.shuffle(arrayList);
Collections.shuffle(arrayList);
// 创建手牌对象(集合);
Set<Integer> 周星驰=new TreeSet<Integer>();
Set<Integer> 刘德华=new TreeSet<Integer>();
Set<Integer> 周润发=new TreeSet<Integer>();
Set<Integer> 底牌=new TreeSet<Integer>();
//发牌:
/*
* 周星驰:0 3 6 9....
* 刘德华:1 4 7 10....
* 周润发:2 5 8 11....
*/
for(int x=0;x<arrayList.size();x++) {
if(x>=arrayList.size()-3) {
底牌.add(arrayList.get(x));
}else if(x%3==0) {
周星驰.add(arrayList.get(x));
}else if(x%3==1) {
刘德华.add(arrayList.get(x));
}else if(x%3==2) {
周润发.add(arrayList.get(x));
}
}
//看牌,每个人拿着牌的索引去拍盒子里边找牌
lookPoker("周星驰",周星驰,hashMap);
lookPoker("刘德华",刘德华,hashMap);
lookPoker("周润发",周润发,hashMap);
lookPoker("底牌",底牌,hashMap);
}
public static void lookPoker(String name,Set<Integer> treeSet,HashMap<Integer,String> hashMap) {
System.out.println(name);
for(Integer index:treeSet) {
System.out.print(hashMap.get(index)+" ");
}
System.out.println();
}
}