Как мне скопировать двумерный массив строк? - PullRequest
4 голосов
/ 01 апреля 2009

Я работаю с программой, которая использует двумерные массивы строк (вероятно, не такие умные для начала, но да), и я хотел бы написать функцию, которая принимает один из этих массивов (скажем, массив1 ), создает независимую копию и возвращает ее (скажем, array2). Однако когда я затем изменяю значение в массиве 2, оно, похоже, отражается в массиве 1.

Моя функция сейчас выглядит примерно так:

public static String[][] copy(String[][] matrix, int n) {
    String[][] out = new String[n+1][n+1];
    for (int i = 0; i < n+1; i++) 
        for (int j = 0; j < n+1; j++) {
            if(matrix[i][j] != null) {
                String cp = new String(matrix[i][j]);
                out[i][j] = cp;
            }

        }

    return out;
}

Я объявляю новый массив строк, а затем перебираю его, копируя каждое значение по отдельности. Когда это не сработало, я даже попытался явно объявить новую строку из каждой старой строки и вместо этого поместить ее в массив.

Может кто-нибудь сказать мне, где я иду не так?

Ответы [ 7 ]

5 голосов
/ 01 апреля 2009

Я не уверен, для чего нужен параметр n, но если бы мне нужна была такая функция, я бы использовал что-то вроде этого:

public static String[][] copy(String[][] matrix) {
  String[][] copy = new String[matrix.length];
  for (int idx = 0; idx < matrix.length; ++idx)
    copy[idx] = matrix[idx].clone();
  return copy;
}

Вам не нужно создавать копию String, потому что они неизменны. Как отметил Майкл в комментариях, конструктор String(String) может быть полезен, если исходная строка была создана как подстрока некоторой очень большой строки. Другое использование - когда вы используете String объекты в качестве блокировок (не рекомендуется) и хотите, чтобы частный экземпляр избежал взаимоблокировок.

Кроме того, нет необходимости проверять, является ли элемент нулевым, перед назначением; если у вас правильно настроены циклы, элемент гарантированно будет нулевым. (А если это не так, то какой вред перезаписывать это?)

3 голосов
/ 01 апреля 2009

Ваш метод выглядит так, как будто он должен работать, хотя передача n в качестве параметра делает его хрупким, использование поля длины входного массива было бы лучше, и вы могли бы даже обрабатывать неровные массивы таким образом.

Создание копии содержимого не является необходимым, поскольку строки не могут быть изменены - что приводит к основному вопросу: какие изменения вы делаете, которые, кажется, отражаются в копии? Покажите нам код, который делает это.

3 голосов
/ 01 апреля 2009

Посмотрите на System.arraycopy . Таким образом, вы можете избавиться от внутреннего цикла.

1 голос
/ 11 марта 2013

Я пытался с вашим кодом: получил исключение java.lang.ArrayIndexOutOfBoundsException

Это работает для меня, пожалуйста, попробуйте так:

 public static String[][] copy(String[][] matrix, int n) 
 {
     String[][] out = new String[n][n];
     for (int i = 0; i < n; i++) 
       for (int j = 0; j < n; j++) {
        if(matrix[i][j] != null) {
            String cp = new String(matrix[i][j]);
            out[i][j] = cp;
        }
       }
     return out;
 }
1 голос
/ 01 апреля 2009

Может быть Arrays.copyOf пригодится?

0 голосов
/ 02 апреля 2009

Использование вами параметра 'n', как отмечено выше, является избыточным, но также имеет недостатки в вашем коде с n + 1 ?? Ваш код будет генерировать ArrayIndexoutOfBoundsException, если запустить что-то вроде:


String [][] m1 = { {"A", "B"}, {"C", "D" } };
String [][] m2 = copy(m1, 2);

Что, по-видимому, как вы намереваетесь вызвать?

Он также ограничивает вашу функцию квадратными «матрицами» строк. Но что касается проблемы, которую вы указали, я не вижу причин, почему программа должна вести себя так ... Я даже запустил ее, используя приведенный выше вызов (но с n = 1 ???), затем изменил

m2[0][1] = "X";

и m1 не изменились, как и ожидалось. Даже замена самой внутренней строки кода на:


out[i][j] = matrix[i][j];

не меняет этого, так как компилятор переписывает его на то, что вы изначально имели. На самом деле большая часть синтаксиса String является просто синтаксическим сахаром для StringBuffers (например, конкатенация и присваивание). например, компилятор перепишет


String s = "Hello ";
s += "World";        // Makes it appear that String is builtin type!
в

String s = new String("Hello ");
s = new StringBuffer(s).append("World").toString();
Именно поэтому у вас много конкатенаций строк внутри циклов, которые они могут выполнять очень плохо.

Я не понимаю, почему у вас возникла проблема, которую вы указали.

И поскольку вы не изменяете параметр 'matrix', 'Pass By Reference' не имеет к этому никакого отношения.

0 голосов
/ 01 апреля 2009

Взгляните на этот вопрос Является ли Java передачей по ссылке? Может быть немного непонятно, как Java передает объекты, но это объясняет, почему изменение одного массива также приводит к изменению другого массива. массив.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...