简体   繁体   中英

Should I use a HashMap, List, or something else?

I am writing a program that

  1. Stores a list of key-value pairs (scenario, listOfResults)
  2. Randomly simulates a new scenario, finds the result
  3. Checks to see if the scenario is in the list of key-value pairs
  4. If so, updates that key-value pair so that the new result is added to the list
  5. Otherwise, adds the scenario-result pair to the list of key-value pairs
  6. Repeat Steps #2-5

Currently I am using a HashMap, since it's key-value system made sense. However, the calculations seem to take a very long time and I am considering whether a different data structure may be more appropriate.

Simulating 100 scenarios took 8.623 seconds and left the HashMap with 4,600 key-value pairs.

Simulating 200 scenarios took 42.690 seconds and left the HashMap with 9,431 key-value pairs.

It appears that the number of key-value pairs is increasing linearly while the time is increasing exponentially, and will soon spiral out of control. I may be able to further optimize the program, but am I using the wrong data structure entirely?

UPDATE: I suspect the problem is with my hashcode() method. Here it is:

@Override
public int hashCode() {
    int result = 31 + legalBoard;
    result = result*31 + playerToMove;
    result = result*31 + Arrays.hashCode(getSmallestFieldConfiguration());
    //System.out.println("Hashcode: " + result + " ---------- " + Arrays.toString(field));
    return result;
}

legalBoard is an int between -1 and 8. playerToMove is either -1 or 1. field is an int[81] with values -1, 0, and 1. The getSmallestConfiguration() method finds the smallest array out of every possible reflection/rotation of the array, as shown here:

public int[] getSmallestFieldConfiguration(){       
    int[] smallestConfig = field;
    for(int[] config : getAllOtherFieldConfigurations()){
        if(isGreater(smallestConfig, config)){
            smallestConfig = config;
        }
    }
    return smallestConfig;
}

public int[][] getAllOtherFieldConfigurations(){
    int[][] configs = new int[7][];
    int[][] twoDimensionalField = new int[][]{
        {field[0],field[1],field[2],field[3],field[4],field[5],field[6],field[7],field[8]},
        {field[9],field[10],field[11],field[12],field[13],field[14],field[15],field[16],field[17]},
        {field[18],field[19],field[20],field[21],field[22],field[23],field[24],field[25],field[26]},
        {field[27],field[28],field[29],field[30],field[31],field[32],field[33],field[34],field[35]},
        {field[36],field[37],field[38],field[39],field[40],field[41],field[42],field[43],field[44]},
        {field[45],field[46],field[47],field[48],field[49],field[50],field[51],field[52],field[53]},
        {field[54],field[55],field[56],field[57],field[58],field[59],field[60],field[61],field[62]},
        {field[63],field[64],field[65],field[66],field[67],field[68],field[69],field[70],field[71]},
        {field[72],field[73],field[74],field[75],field[76],field[77],field[78],field[79],field[80]},
    };
    /*for(int i=0; i<81; i++){
        twoDimensionalField[i%9][i/9] = field[i];
    }*/

    //Reflections
    configs[0] = getFieldFromMatrix(MatrixTransformations.reflectVertical(twoDimensionalField));
    configs[1] = getFieldFromMatrix(MatrixTransformations.reflectHorizontal(twoDimensionalField));
    //Rotations
    int[][] singleRotation = MatrixTransformations.rotate(twoDimensionalField);
    configs[2] = getFieldFromMatrix(singleRotation);
    int[][] doubleRotation = MatrixTransformations.rotate(twoDimensionalField);
    configs[3] = getFieldFromMatrix(doubleRotation);
    configs[4] = getFieldFromMatrix(MatrixTransformations.rotate(doubleRotation));
    //Transpositions
    configs[5] = getFieldFromMatrix(MatrixTransformations.transpose(twoDimensionalField));
    configs[6] = getFieldFromMatrix(MatrixTransformations.transpose(doubleRotation));

    return configs;
}

The MatrixTransformations methods look like this:

public class MatrixTransformations { public MatrixTransformations(){}

public static int[][] reflectVertical(int[][] arr){
    for(int j=0; j<9; j++){
        for(int k=0; k<4; k++){
            int temp = arr[j][k];
            arr[j][k] = arr[j][3-k];
            arr[j][8-k] = temp;
        }
    }
    return arr;
}
public static int[][] reflectHorizontal(int[][] arr){
    for(int j=0; j<4; j++){
        for(int k=0; k<9; k++){
            int temp = arr[j][k];
            arr[j][k] = arr[8-j][k];
            arr[8-j][k] = temp;
        }
    }
    return arr;
}
public static int[][] transpose (int[][] array) {
      if (array == null || array.length == 0)//empty or unset array, nothing do to here
        return array;

      int width = array.length;
      int height = array[0].length;

      int[][] array_new = new int[height][width];

      for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
          array_new[y][x] = array[x][y];
        }
      }
      return array_new;
    }

public static int[][] rotate(int[][] arr){
    int[][] newArr = new int[9][9];
    for (int i = 0; i < 9; ++i) {
        for (int j = 0; j < 9; ++j) {
            newArr[i][j] = arr[8 - j][i];
        }
    }
    return newArr;
}
}

Probably you should stick with a map. Unless your keys are sequential 1,2,3 Using 9K of random numbers could get you in not enough memory problems.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM