[关闭]
@w460461339 2016-11-16T07:04:36.000000Z 字数 6529 阅读 831

Java学习Day7(Map双排集合 Collections类)

Java基础


嘛,今天学习的是Map这一大类以及Collections类(Collection的工具类)。(妈蛋,好不想写学习文档= -)另外还有一些例子,我们就先从Map开始吧。

1、Map

Map是和Collection并列的顶层接口。这里之所以用并列,是想说明,其实Map和Collection之间并没有什么关系。只是Collection下Set子接口以及其子类中有一些功能方法是通过Map的方法实现的。
Map是双列集合,< K V >一一对应。其下有两个实现类,分别是HashMap以及TreeMap两者最大的区别就是,TreeMap可以对KeySet进行排序。

1.1 Map接口功能概述:

就以下几个功能,具体自己去尝试好了= -
A:添加功能:

V put(K key,V value):添加元素。
如果键是第一次存储,就直接存储元素,返回null
如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值

B:删除功能

void clear():移除所有的键值对元素
V remove(Object key):根据键删除键值对元素,并把值返回

C:判断功能

boolean containsKey(Object key):判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty():判断集合是否为空

D:获取功能

Set<Map.Entry<K,V>> entrySet():返回对象对的集合
V get(Object key):根据键获取值
Set<K> keySet():获取集合中所有键的集合
Collection<V> values():获取集合中所有值的集合

E:长度功能

int size():返回集合中的键值对的对数
1.2 Map的遍历

同样,我们用增强for进行遍历,但是由于它是对象对,我们有两种方法可以遍历:

Way1:运用keySet以及get()进行遍历。即先拿到key的集合,在遍历key的集合,去拿到对应的value。

  1. // 创建集合对象
  2. Map<String, String> map = new HashMap<String, String>();
  3. map.put("邓超", "孙俪");
  4. map.put("黄晓明", "杨颖");
  5. map.put("周杰伦", "蔡依林");
  6. map.put("刘恺威", "杨幂");
  7. Set<String> mapSet = map.keySet();//拿到由key组成的集合
  8. for(String key:mapSet){
  9. String value=map.get(key);//拿到每个key对应的value
  10. System.out.println(value);
  11. }

Way2:利用entrySet以及Entry类的getKey以及getValue方法。即先拿到元素对的集合,然后遍历集合,拿到每个元素对,再去去除key以及value。

  1. Map<String, String> map = new HashMap<String, String>();
  2. map.put("邓超", "孙俪");
  3. map.put("黄晓明", "杨颖");
  4. map.put("周杰伦", "蔡依林");
  5. map.put("刘恺威", "杨幂");
  6. Set<Map.Entry<String,String>> mapSet=map.entrySet();
  7. for(Map.Entry<String,String> key:mapSet){
  8. String name1=key.getKey();
  9. String name2=key.getValue();
  10. System.out.println(name1+"----"+name2);
  11. }
1.3 自定义类作为Map的Key

注意,Map的实现类中,是用Set将Key储存的,所以才能保证Key的唯一性。因此,我们也知道,要让自定义类也能够体现唯一性,需要在自定义类中实行hashCode以及euqals方法。

  1. import java.util.HashMap;
  2. import java.util.Set;
  3. class Student{//缺少hashCode以及equals方法
  4. private String name;
  5. private int age;
  6. public Student() {
  7. super();
  8. // TODO Auto-generated constructor stub
  9. }
  10. public Student(String name, int age) {
  11. super();
  12. this.name = name;
  13. this.age = age;
  14. }
  15. public String getName() {
  16. return name;
  17. }
  18. public void setName(String name) {
  19. this.name = name;
  20. }
  21. public int getAge() {
  22. return age;
  23. }
  24. public void setAge(int age) {
  25. this.age = age;
  26. }
  27. }
  28. public class MyTreeSet {
  29. public static void main(String[] args) {
  30. HashMap<Student, String> tm= new HashMap<Student, String>();
  31. Student s1=new Student("a",1);
  32. Student s2=new Student("b",2);
  33. Student s3=new Student("c",3);
  34. Student s4=new Student("c",3);
  35. tm.put(s1, "first");
  36. tm.put(s2, "second");
  37. tm.put(s3, "third");
  38. tm.put(s4, "third");
  39. //这样的话,下面的遍历输出的是4个元素,并不会把s4与s3看做是同一个元素
  40. Set<Student> tmSet=tm.keySet();
  41. for(Student key:tmSet){
  42. String value=tm.get(key);
  43. System.out.println(value);
  44. }
  45. }
  46. }

所以,在自定义类中右击,源代码,生成hashCode以及equals方法即可(这里就贴一下这重写后的这两个方法了)

  1. @Override
  2. public int hashCode() {
  3. final int prime = 31;
  4. int result = 1;
  5. result = prime * result + age;
  6. result = prime * result + ((name == null) ? 0 : name.hashCode());
  7. return result;
  8. }
  9. @Override
  10. public boolean equals(Object obj) {
  11. if (this == obj)
  12. return true;
  13. if (obj == null)
  14. return false;
  15. if (getClass() != obj.getClass())
  16. return false;
  17. Student other = (Student) obj;
  18. if (age != other.age)
  19. return false;
  20. if (name == null) {
  21. if (other.name != null)
  22. return false;
  23. } else if (!name.equals(other.name))
  24. return false;
  25. return true;
  26. }
1.4 自定义对象作为TreeMap的Key

要令自定义类在TreeMap中同样能够实现TreeMap的特性,除了在自定义类中加上hashCode以及equals方法以外,还需要针对TreeSort的排序功能做一些调整。

TreeSet在Map的基础之上增加了对keySet进行排序的功能。那么和TreeSet一样,需要自定义类去实现(implements)Comparable接口;或者在创建TreeMap对象的时候,传递一个Comparator对象给它的构造器。下面仅演示直接传递Comparator的方法。

  1. TreeMap<Student, String> tm =
  2. new TreeMap<Student, String>(new Comparator<Student>() {
  3. //表示创建了一个匿名类,实现了Comparator接口,并且明确对象类型是Student
  4. //之后在该匿名类中实现了接口中的方法
  5. @Override
  6. public int compare(Student s1, Student s2) {
  7. // 主要条件
  8. int num = s1.getAge() - s2.getAge();
  9. // 次要条件
  10. int num2 = num == 0 ? s1.getName().compareTo(
  11. s2.getName()) : num;
  12. return num2;
  13. }
  14. });
1.5 案例

两个案例,一个是统计字符串中每个字符出现的次数;另一个是集合嵌套遍历。嵌套遍历比较简单的,除了之前说的,自定义类放在key的位置上,需要重写一些方法,实现一些接口,其他弄清楚每一层关系就好。下面来写一下统计每个字符串出现的次数的程序。

需求分析:

A 键盘录入一串字符串
B 将字符串转化为字符数组
C 将每个字符存入TreeSet。先用contains判断,是否为null
    为null,key为该字符,value写1
    不为null,key为该字符,value在原基础上+1
D 显示
  1. import java.util.Scanner;
  2. import java.util.Set;
  3. import java.util.TreeMap;
  4. public class myString {
  5. public static void main(String[] args) {
  6. //录入字符串,并把它们转成字符数组
  7. Scanner in = new Scanner(System.in);
  8. String str=in.nextLine();
  9. char[] chStr=str.toCharArray();
  10. //创建TreeMap对象,注意key和value类型
  11. TreeMap<Character, Integer> chTm=new TreeMap<Character, Integer>();
  12. //遍历字符数组(居然没有用增强for,自己脑抽了),把元素放入TreeMap
  13. for(int i=0;i<chStr.length;i++){
  14. Integer value=chTm.get(chStr[i]);
  15. if(value==null){
  16. chTm.put(chStr[i], 1);
  17. }else{
  18. chTm.put(chStr[i], value+1);
  19. }
  20. }
  21. //遍历TreeMap,输出
  22. Set<Character> tmSet=chTm.keySet();
  23. for(Character key:tmSet){
  24. Integer value =chTm.get(key);
  25. System.out.println(key+"("+value+")");
  26. }
  27. }
  28. }

2、Collections类

注意啊!这货是Collections类,比Collection接口多一个s的!而且人家是货真价实的类,不是接口啊!虽然Collections类中全部是静态方法,直接用类名调用方法就好,不用创建对象,但还是要明确,这货是个类!

主要有这么几个方法比较重要:

    A:public static <T> void sort(List<T> list) 排序
    B:public static <T> int binarySearch(List<?> list,T key) 二分查找
    C:public static <T> T max(Collection<?> coll)最大值
    D:public static void reverse(List<?> list)反转
    E:public static void shuffle(List<?> list)乱序

注意,除了找最大值以外,其他都只对List下的类开放,Set什么的退散。另外,二分查找是在序列排序之后才有用的,所以记得先对序列进行排序之后在二分查找。

测试什么的,这里就不写了,自己慢慢试试就好。

3、实例测试:模拟斗地主洗牌,发牌,看牌功能

需求:

54张牌,随机发给三个人,并留下三张牌,最后按照一定顺序查看

思路:

    A:按照一定的顺序将54张牌存储在HashMap中,每张牌的面值对应一个编号,从0到53
    B:将这54个编号单独存储在ArrayList中,利用shuffle打乱,并用下标作为索引分发
    C:每个人以及底牌用TreeSet进行储存,实现自然排序
    D:遍历,展示
  1. import java.util.ArrayList;
  2. import java.util.Collections;
  3. import java.util.HashMap;
  4. import java.util.TreeSet;
  5. public class myDoudizhu {
  6. public static void main(String[] args) {
  7. //创建花色
  8. String[] color={"♥","♠","♣","◇"};
  9. //创建牌号
  10. String[] number={"3","4","5","6","7",
  11. "8","9","10","J","Q","K","A","2",};
  12. //创建计数器以及牌盒
  13. Integer cnt=0;
  14. HashMap<Integer, String> hm=new HashMap<Integer, String>();
  15. //创建记录编号的ArrayList
  16. ArrayList<Integer> array=new ArrayList<Integer>();
  17. //往牌盒中放牌,并网array中塞入编号
  18. for(String nuKey:number){
  19. for(String coKey:color){
  20. hm.put(cnt, coKey.concat(nuKey));
  21. array.add(cnt);
  22. cnt++;
  23. }
  24. }
  25. hm.put(cnt,"小王");
  26. array.add(cnt);
  27. cnt++;
  28. hm.put(cnt,"大王");
  29. array.add(cnt);
  30. //洗牌
  31. Collections.shuffle(array);
  32. //创建打牌的人
  33. TreeSet<Integer> player1=new TreeSet<Integer>();
  34. TreeSet<Integer> player2=new TreeSet<Integer>();
  35. TreeSet<Integer> player3=new TreeSet<Integer>();
  36. TreeSet<Integer> dipai=new TreeSet<Integer>();
  37. //发牌;此处注意,只是把每张牌在HahsMap中编号(Key)发了
  38. //按照每轮每人一张,最后3张留作底牌的顺序发牌
  39. for(int i=0;i<array.size();i++){
  40. Integer key=array.get(i);
  41. if(i>=array.size()-3){
  42. dipai.add(key);
  43. }else if(i%3==0){
  44. player1.add(key);
  45. }else if(i%3==1){
  46. player2.add(key);
  47. }else if(i%3==2){
  48. player3.add(key);
  49. }
  50. }
  51. //每个人都得到了13个编号,底牌得到3个编号,并且由TreeSet自然排序好
  52. //靠这个顺序,以及按照HashMap中我们定义顺序去除牌,并显示
  53. //完成最终的斗地主顺序的现实牌
  54. showCard("player1",player1,hm);
  55. showCard("player2",player2,hm);
  56. showCard("player3",player3,hm);
  57. showCard("底牌",dipai,hm);
  58. }
  59. public static void showCard(String name,TreeSet<Integer> card,HashMap<Integer, String> hm){
  60. System.out.print(name);
  61. for(Integer key:card){
  62. String value=hm.get(key);
  63. System.out.print("\t"+value);
  64. }
  65. System.out.println();
  66. }
  67. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注