JAVA学习笔记--HashMap

HashMap

操作

  • 实例化: HashMap<String,Integer> codeMap = new HashMap<>();
    • <,>中的数据类型根据存储的需要可以改变
  • 常用方法:
    • 存入数据: codeMap.put(“a”,1);
    • 取出某个Key对应的Value: codeMap.get(key);

存储原理

  • HashMap是一个散列表(Hash table),存放键值对(Key-Value)映射。当我们存储键值对时,以 codeMap.put(“a”,1) 为例,
    需要先计算出a的哈希码(hashcode),然后对于已经给定长度为length的数组(长度一般为16),将 “a”-1 这组键值对存放在
    arr[hashcode%length]上。
  • 当然,我们只需要写一句 codeMap.put(“a”,1); 就可以了,剩下的工作是由系统完成的。

hash冲突

  • 由于散列表的空间<<输入的空间,所以当输入很多时,两个不同的Key可能会生成相同的hashcode,所以不能再通过hash值来确定
    唯一的Key,这就是hash冲突。简而言之,这是把任意长度的信息压缩成固定长度的信息带来的问题。
  • 解决方法:
    • codeMap.put(“a”,1);codeMap.put(“b”,2); 若a,b的hashcode相同,则在这个位置使用链表存储a,b等元素。
    • 当链表的元素很多时(>8)会影响查询效率,将链表改为红黑树。

应用(最近所学)

  • 在设计五子棋程序时,可以根据棋盘上每个点的情况打分:
    • 连子情况(Key) - 权值(Value) 1黑棋 2白棋 0无子
    • 活连:
      010(020) 50
      0110(0220) 150
      01110(02220) 500
      011110(022220) 3000
    • 眠连:
      01(02) 30
      011(022) 90
      0111(0222) 300
      01111(02222) 1800
package HashMap;

import java.util.HashMap;

public class AI {
    static HashMap<String,Integer> codeMap = new HashMap<>();
    static int[][] codeArray = new int[16][16];

    static{
        codeMap.put ("010", 50);
        codeMap.put ("0110", 150);
        codeMap.put ("01110", 500);
        codeMap.put ("011110", 3000);

        codeMap.put ("020", 50);
        codeMap.put ("0220", 150);
        codeMap.put ("02220", 500);
        codeMap.put ("022220", 3000);

        codeMap.put ("01", 30);
        codeMap.put ("011", 90);
        codeMap.put ("0111", 300);
        codeMap.put ("01111", 3000);

        codeMap.put ("02", 30);
        codeMap.put ("022", 90);
        codeMap.put ("0222", 300);
        codeMap.put ("02222", 3000);
    }

    public static void main(String[] args) {
        int[][] arr = {
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
        };
        getCodeArray(arr);

        for (int i = 0; i < codeArray.length; i++){
            for(int j = 0; j < codeArray[i].length; j++){
                System.out.print(codeArray[i][j]+"  ");
            }
            System.out.println();
        }
    }
    //计算所有可下棋位置的权值
    private static void getCodeArray(int[][] arr){
        for(int i = 0; i < arr.length; i++){
            for(int j = 0; j < arr[i].length; j++){
                int chessNum = arr[i][j];
                // 遍历所有的空格
                if(chessNum == 0){
                    toRight (i, j, arr);
                    toLeft(i, j, arr);
                    toUpper(i, j, arr);
                    toUnder(i, j, arr);
                }
            }
        }
    }
    //判断向右的连子情况
    //用codeStr(String)记录连子情况  如"01110"
    static private void toRight(int i, int j, int[][] chessArray){
        int chessNum = chessArray[i][j];
        //如果右侧为0/墙  return
        if(j+1>=chessArray[i].length || chessArray[i][j+1]==0)
            return;
        //右侧有子时 用chessNumR1记录其颜色
        int chessNumR1 = chessArray[i][j+1];
        //01->"01"  便于后续调用codeMap.get();
        String codeStr = ""+chessNum+chessNumR1;
        //从右侧的第二颗棋子开始 判断是否与chessNumR1颜色相同
        //活连 眠连两种情况 只需判断chessNumRn是否==0
        for(int k = j+2; k < chessArray[i].length; k++){
            int chessNumRn = chessArray[i][k];
            if(chessNumRn != 0){
                if(chessNumR1==chessNumRn)
                    //"01" -> "011"
                    codeStr += chessNumR1;
                else if (chessNumR1!=chessNumRn) {
                    break;
                }
            }else{
                //活连 "011"->"0110"
                codeStr += "0";
                break;
            }
        }
        System.out.println("("+(i+1)+","+(j+1)+")"+"向右连子情况:"+codeStr);
        Integer codeValue = codeMap.get(codeStr);
        if(codeValue==null)
            return;
        codeArray[i][j]+=codeValue;
    }

    static private void toLeft(int i, int j, int[][] chessArray){
        int chessNum = chessArray[i][j];
        if(j-1<0 || chessArray[i][j-1]==0)
            return;
        int chessNumL1 = chessArray[i][j-1];
        String codeStr = ""+chessNum+chessNumL1;
        for (int k=j-2; k>=0; k--){
            int chessNumLn = chessArray[i][k];
            if(chessArray[i][k]!=0){
                if (chessNumLn == chessNumL1){
                    codeStr += chessNumL1;
                } else {
                    break;
                }
            } else {
                codeStr += "0";
                break;
            }
        }
        System.out.println("("+(i+1)+","+(j+1)+")"+"向左连子情况:"+codeStr);
        Integer codeValue = codeMap.get(codeStr);
        if(codeValue == null)
            return;
        codeArray[i][j] += codeValue;
    }

    static private void toUpper(int i, int j, int[][] chessArray){
        int chessNum = chessArray[i][j];
        if(i-1<0 || chessArray[i-1][j] == 0)
            return;
        int chessNumU1 = chessArray[i-1][j];
        String codeStr = "" + chessNum + chessNumU1;
        for (int k = i-2; k >= 0; k--){
            int chessNumUn = chessArray[k][j];
            if(chessNumUn != 0){
                if (chessNumUn == chessNumU1)
                    codeStr += chessNumU1;
                else break;
            }else {
                codeStr += "0";
                break;
            }
        }
        System.out.println("("+(i+1)+","+(j+1)+")"+"向上连子情况:"+codeStr);
        Integer codeValue = codeMap.get(codeStr);
        if (codeValue == null)
            return;
        codeArray[i][j] += codeValue;
    }

    static private void toUnder(int i, int j, int[][] chessArray){
        int chessNum = chessArray[i][j];
        if(i+1>= chessArray.length || chessArray[i+1][j] == 0)
            return;
        int chessNumU1 = chessArray[i+1][j];
        String codeStr = ""+chessNum+chessNumU1;
        for(int k = i+2; k<chessArray.length; k++){
            int chessNumUn = chessArray[k][j];
            if(chessNumUn != 0){
                if (chessNumUn == chessNumU1)
                    codeStr += chessNumU1;
                else break;
            }else {
                codeStr += "0";
                break;
            }
        }
        System.out.println("("+(i+1)+","+(j+1)+")"+"向下连子情况:"+codeStr);
        Integer codeValue = codeMap.get(codeStr);
        if(codeValue == null)
            return;
        codeArray[i][j] += codeValue;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值