在二维网格上打印HashMap对象

时间:2016-05-15 15:59:49

标签: java hashmap

这是我需要在Conway的生命游戏实现中使用的简化代码片段。我有一个HashMap,其中存储了Coord Objects(生命游戏中的单元格)。 Coord对象是X,Y坐标对,我想在简单的2D网格上打印。

我的printGrid(HashMap<Coord, Integer> map)方法存在问题,主要是:

  1. 是否有更简单,更优雅的方式在2维网格上打印Coord对象?

  2. 如果没有,有没有办法检查HashMap中是否存在具有给定X,Y参数的Coord对象,而没有为网格上的每个X,Y位置创建Coord对象的实例,就像我'我在这里做:

    if (map.containsKey(new Coord(column,row))) {
        grid +=  map.get(new Coord(column,row));
    } else {
        grid += "#";
    }
    
  3. 代码:

    public class Main {
    
        static class Coord {
            int x;
            int y;
    
            public boolean equals(Object o) {
                Coord c = (Coord) o;
                return c.x == x && c.y == y;
            }
    
            public Coord(int x, int y) {
                super();
                this.x = x;
                this.y = y;
            }
    
            public int hashCode() {
                return x * 3 + y * 5;
            }
        }
    
        public static String printGrid(HashMap<Coord, Integer> map) {
    
            int grid_width = 10;
            int grid_height = 10;       
            String grid = "";
    
            for(int row =0; row < grid_height; row++) {
                for(int column=0; column< grid_width; column++) {
                    if(map.containsKey(new Coord(column,row))) {
                        grid +=  map.get(new Coord(column,row));
                    } else {
                        grid += "#";
                    }
                }
                grid += "\n"; // next row
            }
    
            return grid;        
        }
    
        public static void main(String args[]) {        
    
            HashMap<Coord, Integer> map = new HashMap<Coord, Integer>();
    
            map.put(new Coord(0, 0), 1);
            map.put(new Coord(1, 2), 5);
            map.put(new Coord(3, 4), 1);
            map.put(new Coord(4, 5), 3);
            map.put(new Coord(4, 6), 2);        
    
            System.out.println(printGrid(map));
        }
    
    }
    

4 个答案:

答案 0 :(得分:0)

您的代码接近您想要的,但是:

  • 由于网格非常大,printGrid()如何知道大小?您也应该将大小作为参数传递。

  • 不要两次创建Coord对象。只创建一次并分配给变量,因此可以使用两次 这一点被下一个子弹否定了,但是做得好,对吗?

  • 请勿致电containsKey(),然后致电get()。由于您的地图不会有空值(根据您使用它的方式),get()返回的空值足以存在测试。

  • 不要在循环中执行string += string。使用StringBuilder。当字符串变大时,性能差异很大。

因此,您的代码变为:

public static String printGrid(HashMap<Coord, Integer> map, int width, int height) {

    StringBuilder grid = new StringBuilder(height * (width + 1)); // Pre-sizing is optional, but
                                                                  // may improve performance a bit

    for (int row = 0; row < height; row++) {
        for (int column = 0; column < width; column++) {
            Integer value = map.get(new Coord(column, row));
            if (value != null) {
                grid.append(value);
            } else {
                grid.append('#');
            }
        }
        grid.append('\n'); // next row
    }

    return grid.toString();
}

答案 1 :(得分:0)

考虑到安德烈亚斯的建议,这是我的主张

Coord

中添加 int neighbors
static class Coord {
    int x;
    int y;
    int neighbours;

    public Coord(int x, int y) {
        this(x, y, 0);
    }

    public Coord(int x, int y, int neighbours) {
        this.x = x;
        this.y = y;
        this.neighbours = neighbours;
    }

    // getters and setters here

    // Equals method here

}

添加一个从坐标

中检索Coord对象的方法
Coord getCoord(HashSet<Coord> data, int x, int y) {
    Coord coord = new Coord(x, y);
    if (data.contains(coord)) {
        for (Coord c : data) {
            if (c.equals(coord)){
                return c;
            }
        }
    }
    return null;
}

您的 printGrid 方法将如下

String printGrid(HashSet<Coord> data, int width, int height) {
    StringBuilder grid = new StringBuilder(height * (width + 1));
    Coord coord;

    for (int row = 0; row < height; row++) {
        for (int column = 0; column < width; column++) {
            coord = getCoord(data, row, column);
            if(coord != null) {
                grid.append(coord.getNeighbours());
            } else {
                grid.append('#');
            }
        }
        grid.append('\n'); // next row
    }

    return grid.toString();        
}

在您的方法中,您将拥有此

HashSet<Coord> data = new HashSet<>();

data.add(new Coord(0, 0, 1));
data.add(new Coord(1, 2, 5));
data.add(new Coord(3, 4, 1));
data.add(new Coord(4, 5, 3));
data.add(new Coord(4, 6, 2));        

System.out.println(printGrid(data, 10, 10));

你也可以像这样使用 ArrayList

Coord getCoordWithList(ArrayList<Coord> data, int x, int y) {
    Coord coord = new Coord(x, y);
    int index = data.indexOf(coord);
    if (index > -1) {
        return data.get(index);
    }
    return null;
}

答案 2 :(得分:0)

我认为以下代码符合您的要求。基本上您可以创建一个StringBuilder对象并使用所有'#'对其进行初始化。然后,基于地图中的Coord对象,使用map中的值替换构建器中的相应字符。这很简单,您不需要为每个网格单元创建Coord对象。

public static String printGrid(HashMap<Coord, Integer> map) {

int width = 10;
int height = 10;

int lenght = height * width ;

StringBuilder grid = new StringBuilder(lenght);     

// Initialize the builder
int i = 0 ;
  while(i<lenght){
    if(i >= width && i%(width)==0){
            grid.append('\n');
    }
   grid.append('#');        
  i++;
 }

for(Coord c : map.keySet()){
    int index = c.x *(width + 1) + c.y;
      grid.setCharAt(index, map.get(c).toString().charAt(0));
}

 return grid.toString();        
}

输出:

  1#########
  ##5#######
  ##########
  ####1#####
  #####32###
  ##########
  ##########
  ##########
  ##########
  ##########
希望这可以提供帮助。

答案 3 :(得分:-1)

除了使用 Coord 对象作为键的映射外,您可以使用String作为键。您的字符串键将是 Coord x y 值的串联。

所以你会有这个

for (int row = 0; row < grid_height; row++) {
    for (int column = 0; column < grid_width; column++) {
        String key = column + "#" + row;
        if(map.containsKey(key)) {
            grid += map.get(key) + "";
        } else {
            grid += "#";
        }
    }
    grid += "\n"; // next row
}

对于地图的初始化,您将拥有此

HashMap<String, Integer> map = new HashMap<String, Integer>();

map.put("0#0", 1);
map.put("1#2", 5);
map.put("3#4", 1);
map.put("4#5", 3);
map.put("4#6", 2);        

System.out.println(printGrid(map));

修改

您可以只使用HashSet代替使用HashMap来存储数据。地图的整数值将是 Coord 类的属性