【问题标题】:How do I copy a two dimensional array of strings?如何复制二维字符串数组?
【发布时间】:2010-10-16 22:41:39
【问题描述】:

我正在使用一个使用二维字符串数组的程序(一开始可能不是那么聪明,但是嗯),我想编写一个函数来获取这些数组之一(比如说 array1 ),制作一个独立的副本,并返回它(比如说array2)。但是,当我随后更改 array2 中的值时,它似乎反映在 array1 中。

我的函数目前看起来像这样:

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;
}

我声明了一个新的字符串数组,然后遍历它,分别复制每个值。当这不起作用时,我什至尝试从每个旧字符串中显式声明一个新字符串并将其放入数组中。

谁能告诉我哪里出错了?

【问题讨论】:

  • 似乎它应该对我有用...您能否提供一些示例代码来说明您遇到的问题?
  • +1:对我来说很好用...你能提供整个测试设置的代码吗?
  • 有编辑功能吗?抱歉,我意识到问题实际上出在我的打印功能上。不过,感谢您的彻底帮助:我根据建议清理了函数,并学到了很多关于 Java 如何传​​递参数的知识。
  • 其实有一个编辑功能...继续,找到并使用它:-) ...
  • 为我工作。提供一个小而完整的例子说明这不起作用,或者这不是一个问题。

标签: java arrays pointers string


【解决方案1】:

我不确定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 的副本,因为它们是不可变的。正如 Michael 在 cmets 中所指出的,如果将原始字符串创建为某个非常大字符串的子字符串,String(String) 构造函数可能会很有用。另一个用途是当您使用 String 对象作为锁(不推荐),并希望使用私有实例来避免死锁时。

另外,在分配之前检查元素是否为空是不必要的;如果您的循环设置正确,则该元素保证为空。 (如果不是,覆盖它有什么害处?)

【讨论】:

  • 使用 String(String) 的另一个有用的原因可能是强制修剪大型基本字符串的子字符串,以便可以回收基本字符串的内存(因为 substring() 通常保留对整个基本字符串)
  • 由于String是不可变的,所以不需要克隆。
  • @Michael:好点;将相应更新。 @Steve:没有人克隆任何字符串。你能解释一下你在说什么吗?
【解决方案2】:

您的方法看起来应该可以工作,尽管将 n 作为参数传递会使它变得脆弱,但使用输入数组的长度字段会更好,您甚至可以用这种方式处理锯齿状数组。

没有必要复制内容,因为字符串无法更改 - 这导致了主要问题:您正在进行哪些似乎反映在副本中的更改?向我们展示执行此操作的代码。

【讨论】:

    【解决方案3】:

    看看System.arraycopy。这样你就可以摆脱内部循环。

    【讨论】:

      【解决方案4】:

      也许Arrays.copyOf 会有用处?

      【讨论】:

        【解决方案5】:

        我尝试了您的代码:出现异常 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;
         }
        

        【讨论】:

          【解决方案6】:

          看看这个问题Is Java pass by reference? Java 传递对象的方式可能有点令人困惑,但这可以解释为什么对一个数组进行更改也会对另一个数组进行更改。

          【讨论】:

          • -1 对于给出的代码,它没有解释为什么对一个数组进行更改也会更改另一个数组。
          • 那是 b/c 问题不在于给出的代码,请重新阅读问题的第一部分。从问题 cmets “我用建议清理了函数,并学到了很多关于 Java 如何传​​递参数的知识。——莉莉”
          【解决方案7】:

          如上所述,您对“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'与它无关。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-06-10
            • 2021-07-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-01-28
            相关资源
            最近更新 更多