我在等待很长时间执行代码并将其指向此方法后得到此错误
public Iterable<Board> neighbors() {
Queue<Board> q = new LinkedList<>();
int n = dimension();
int x = 0, y = 0;
outer:
// do some stuff to get the x and y
if (y+1 < n) {
the line where i get the error -> int [][]arr = new int[n][n];
for (int i = 0; i < tiles.length; i++) {
arr[i] = Arrays.copyOf(tiles[i], n);
}
// do some stuff
Board br = new Board(arr);
if(!this.equals(br)) {
q.add(new Board(arr));
}
}
if (y-1 >= 0) {
int [][]arr = new int[n][n];
for (int i = 0; i < tiles.length; i++) {
arr[i] = Arrays.copyOf(tiles[i], n);
}
// do some stuff
Board br = new Board(arr);
if(!this.equals(br)) {
q.add(new Board(arr));
}
}
if (x-1 >= 0) {
int [][]arr = new int[n][n];
for (int i = 0; i < tiles.length; i++) {
arr[i] = Arrays.copyOf(tiles[i], n);
}
// do some stuff
Board br = new Board(arr);
if(!this.equals(br)) {
q.add(new Board(arr));
}
}
if (x+1 < n) {
int [][]arr = new int[n][n];
for (int i = 0; i < tiles.length; i++) {
arr[i] = Arrays.copyOf(tiles[i], n);
}
// do some stuff
Board br = new Board(arr);
if(!this.equals(br)) {
q.add(new Board(arr));
}
}
return q;
}
我基本上需要复制tiles数组并对副本“arr”进行更改,但保留tiles数组而不更改以便稍后使用..我真的不喜欢我正在做的方式复制和粘贴代码我认为它效率低但却没有其他方式出现在我的脑海里所以我想知道为什么我会得到这个错误“我知道它因为GC需要更多时间而不做很多”但我想知道为什么它在这种情况下也会发生,如果有更好的方法来复制数组。 还我将堆内存增加到-Xmx1600m
感谢您的时间。
答案 0 :(得分:1)
很可能是因为在短时间中创建了大量对象而产生了问题。有关详细信息,请参阅this answer。
目前,一个Board
至少包含四个对象:
arr
arr
我们的目标是创建更少的对象(数组)。由于您只想处理小型电路板,我们可以使用一个long
来存储完整的3×3电路板。 long
有64位。我们使用每个字段64/9 = 7位来存储该字段的值:
state = ... 0000100 0000011 0000010 0000001 0000000
4th field ↑ 2nd field ↑ 0th field
3rd field 1st field
以下类处理位操作。
class Board {
private final static int SIDE_LENGTH = 3;
private final static int FIELDS = SIDE_LENGTH * SIDE_LENGTH;
private final static int BITS_PER_FIELD = 64 / FIELDS;
private final static long FIELD_MASK = (1 << BITS_PER_FIELD) - 1;
private long state;
public Board() {
for (int field = 0; field < FIELDS; ++field) {
set(field, field);
}
}
/** Copy constructor. */
public Board(Board other) {
this.state = other.state;
}
public int get(int x, int y) {
return get(coordinatesToField(x, y));
}
public void set(int x, int y, int value) {
set(coordinatesToField(x, y), value);
}
private int coordinatesToField(int x, int y) {
return SIDE_LENGTH * y + x;
}
private int get(int field) {
return (int) ((state >>> (field * BITS_PER_FIELD)) & FIELD_MASK);
}
private void set(int field, int value) {
int shift = field * BITS_PER_FIELD;
state &= ~(FIELD_MASK << shift);
state |= (long) value << shift;
}
public String toString() {
StringBuilder sb = new StringBuilder();
for (int field = 0; field < FIELDS; ++field) {
sb.append(get(field));
sb.append((field + 1) % SIDE_LENGTH == 0 ? "\n" : "\t");
}
return sb.toString();
}
// TODO implement equals and hashCode
}
使用这个类时,你不必再处理数组,这不仅可以保存很多对象,还可以保存你的prorgram中的复制代码。
该类也适用于1×1,2×2和4×4板,但由于64位限制,不适用于较大的板。
public static void main(String[] args) {
// Create and print the initial board
// 0 1 2
// 3 4 5
// 6 7 8
Board b = new Board();
System.out.println(b);
// Copy an existing board
Bord copy = new Board(b);
// Set the upper right field to value 8
copy.set(2, 0, 8);
// Print the center field
// 4
Syste.out.println(copy.get(1, 1));
}
您甚至可以避免创建Board
个对象,只存储long
值。但是当你使用泛型(例如LinkedList
)时,由于Java的自动装箱,这没有用。
另请注意,LinkedList
将每个条目包装在其他节点对象中。也许您可以像循环缓冲区一样使用更高效的DataStructure。
根据您的工作情况,您可以查看Flyweight design pattern。