Проблемы при использовании StringBuilder вместо String
Имеется HashSet<String> list = new HashSet<String>() и два метода для работы с ним:
void addL(String[][] field) {
String current = new String();
for(int r=0; r<4 ; r++){
for(int c=0; c<10 ; c++){
current += String.valueOf(field[r][c]);
}
}
list.add(current);
}
boolean repeatL(String[][] field, String side) {
String current = new String();
for(int r=0; r<4 ; r++){
for(int c=0; c<10 ; c++){
current += String.valueOf(field[r][c]);
}
}
if(side=="white" & list.contains(current)){
return true;
}
else{
return false;
}
}
В таком виде всё работает без проблем, хотя и не быстро.
Затем в справочниках прочитал, что при "активном" использовании циклов для производительности лучше StringBuilder вместо String. Заменил везде одно на другое (и конкатенацию, соответственно, на append) - поначалу работает нормально, но через некоторое время вылетает с ошибкой превышения размера StringBuilder. Установил определённый параметр capacity: здесь вылеты прекратились, зато они появились в другом месте программы (при работе с большим количеством ArrayList -ов) с ошибкой OutOfMemoryError: Java heap space. Непонятно, что не так, если использование String наоборот, должно потреблять больше ресурсов...
Менял на такое:
HashSet<StringBuilder> list = new HashSet<StringBuilder>();
void addL(String[][] field) {
int r = field.length;
int c = field[0].length;
StringBuilder current = new StringBuilder(field.length * field[0].length);
for(r=0; r<field.length ; r++){
for(c=0; c<field[0].length ; c++){
current.append(field[r][c]);
}
}
list.add(current);
}
boolean repeatL(String[][] field, String side) {
int r = field.length;
int c = field[0].length;
StringBuilder current = new StringBuilder(field.length * field[0].length);
for(r=0; r<field.length ; r++){
for(c=0; c<field[0].length ; c++){
current.append(field[r][c]);
}
}
if(side=="white" & list.contains(current)){
return true;
}
else{
return false;
}
}
Ответы (2 шт):
Такой вариант тоже вроде рабочий, но даёт ли он выигрыш в производительности по сравнению с изначальным я не знаю...
HashSet<String> list = new HashSet<String>();
void addL(String[][] field) {
int r = field.length;
int c = field[0].length;
StringBuilder current = new StringBuilder(field.length * field[0].length);
for(r=0; r<field.length ; r++){
for(c=0; c<field[0].length ; c++){
current.append(field[r][c]);
}
}
String hash = current.toString();
list.add(hash);
}
boolean repeatL(String[][] field, String side) {
int r = field.length;
int c = field[0].length;
StringBuilder current = new StringBuilder(field.length * field[0].length);
for(r=0; r<field.length ; r++){
for(c=0; c<field[0].length ; c++){
current.append(field[r][c]);
}
}
String hash = current.toString();
if(side=="white" & list.contains(hash)){
return true;
}
else{
return false;
}
Попробуйте так:
HashSet<String> list = new HashSet<>();
void addL(String[][] field) {
StringBuilder current = new StringBuilder();
for (int i = 0; i < field.length; i++) {
for (int j = 0; j < field[0].length; j++)
current.append(field[i][j]);
}
list.add(current.toString());
}
boolean repeatL(String[][] field, String side) {
StringBuilder current = new StringBuilder();
for (int i = 0; i < field.length; i++) {
for (int j = 0; j < field[0].length; j++)
current.append(field[i][j]);
}
return (side.equals("white") && list.contains(current.toString()));
}