かすみん日記

暇なときに何か喋ります

【Java】配列のclone()について

Javaにおいて、配列に対してclone()というメソッドが使える。

clone()メソッドは、配列を「コピー」してくれるのだが、モノによってはshallow copyにもdeep copyにもなりうる。

1次元配列の場合は、deep copyになる。

public class Main {
  public static void main(String[] args) {
    int[] a = {0, 1, 2};
    int[] b = a.clone();

    b[0] = 9;

    for (int n : a) {
      System.out.printf("%d ", n);
    }
    System.out.println();
    for (int n : b) {
      System.out.printf("%d ", n);
    }
  }
}

結果:

0 1 2
9 1 2

しかし、2次元配列の場合は、shallow copyになる。

public class Main {
  public static void main(String[] args) {
    int[][] c = {{1, 2}, {3, 4}};
    int[][] d = c.clone();
    
    d[0][0] = 9;
    
    for (int[] nn : c) {
      for (int n : nn){
        System.out.printf("%d ", n);
      }
      System.out.println();
    }
    System.out.println();
    for (int[] nn : d) {
      for (int n : nn){
        System.out.printf("%d ", n);
      }
      System.out.println();
    }
  }
}

結果:

9 2 
3 4 

9 2 
3 4 

2次元配列をdeep copyしたいなら、1次元ずつcloneする。

public class Main {
  public static void main(String[] args) {
    int[][] c = {{1, 2}, {3, 4}};
    int[][] d = new int[c.length][c[0].length];
    for (int i = 0; i < c.length; i++){
      d[i] = c[i].clone();
    }
    
    d[0][0] = 9;
    
    for (int[] nn : c) {
      for (int n : nn){
        System.out.printf("%d ", n);
      }
      System.out.println();
    }
    System.out.println();
    for (int[] nn : d) {
      for (int n : nn){
        System.out.printf("%d ", n);
      }
      System.out.println();
    }
  }
}

結果:

1 2 
3 4 

9 2 
3 4 

結局、clone()メソッドを使ったところで、愚直なdeep copyよりforループが1つ少なくて済むだけという話。

愚直なdeep copy

public class Main {
  public static void main(String[] args) {
    int[][] c = {{1, 2}, {3, 4}};
    int[][] d = new int[c.length][c[0].length];
    for (int i = 0; i < c.length; i++){
      for (int j = 0; j < c.length; j++){
        d[i][j] = c[i][j];
      }
    }
    
    d[0][0] = 9;
    
    for (int[] nn : c) {
      for (int n : nn){
        System.out.printf("%d ", n);
      }
      System.out.println();
    }
    System.out.println();
    for (int[] nn : d) {
      for (int n : nn){
        System.out.printf("%d ", n);
      }
      System.out.println();
    }
  }
}

というわけで、この記事にはオチがないです。

以上。

参考

fksekiguchi.sakura.ne.jp

www.sejuku.net