java의 Array에는 배열의 모든 원소를 특정한 값으로 초기화 하기 위한 메서드가 있습니다. fill과 setAll이라는 메소드입니다. 간단하게 차이점을 알아보겠습니다.

 


 먼저 fill입니다. specified int value. specified value. 특정한 값으로 모든 원소를 초기화 합니다. 예를 들어 배열 내의 원소를 모두 5로 초기화 시키거나 할 때 쓸 법 합니다. 이 메서드는 int형 배열 뿐만이 아니라, long, char, ... 등의 배열을 받기도 합니다. 오버로딩 되어있다고 보면 됩니다. 이 블로그에서는 int형 배열만 다룹니다.

 

 예제를 보겠습니다.

 

 단순하게 Arrays.fill(a, 5);를 호출합니다. 그러면 10개의 원소를 저장하는 배열의 원소들이 모두 5로 초기화 됨을 볼 수 있습니다.

 

 실행 결과는 위와 같습니다.

 


 setAll은 array와 generator를 받습니다. generator는 하나의 함수입니다. 인덱스에 대해 받아들일. 그리고, 해당 위치에 대해서 바라는 값을 생산합니다. 이게 무슨 이야기인가? 배열은 위치가 있습니다. 인풋은 위치, 아웃풋은 위치가 들어오면 뽑아내는 값을 의미합니다. 적용되는 함수에 의해서. 다시 정리해 보겠습니다.

 

 function(위치)를 정의하는 generator이다. function(x)는 x번째 위치에 대해 적용될 값이다. 고로, f(x) = 5이면 배열 내의 모든 값을 5로 초기화 하는 것과 동치일 겁니다. 예제를 보겠습니다.

 

 Arrays.setAll(a, x -> 5); 랍니다. x는 위치를 의미합니다. 모든 위치에 대해서 output이 5입니다. 그러면 값이 어떻게 나올까요? 0번째 위치도 5로, 1번째 위치도 5로, ... , 마지막 위치도 5로 초기화 합니다. 즉, 모든 원소를 5로 초기화 합니다.

 

 실행 결과는 위와 같습니다. 이러면 Arrays.fill과 별 차이가 없어 보입니다? 그런데 하나 다른점은 x번째 위치에 적용될 값을 function으로 적용할 수 있다는 점입니다. 예를 들어, i번째 위치의 값은 2*i로 적용한다고 해 보겠습니다.

 

 

 그러면, 위와 같이 적용할 수 있습니다. setAll의 2번째 인자에 index -> 2 * index를 넣었음을 알 수 있습니다. 이는 index번째 위치에 있는 값은 2 * index를 적용하라는 의미입니다.

 

 실행 결과는 위와 같습니다.

 

 


 또 다른 차이점은 없을까요? Object 배열을 생각해 봅시다.

 

 x -> new Obj(3)을 generator로 넘겨주었습니다. 이 Obj는 x라는 필드만 가집니다. 그리고 0번째 원소의 필드 x를 10으로 바꾸었습니다. 결과는 어떻게 나올까요?

 

 Obj의 toString은 필드 x값만을 뽑는 것입니다. 결과를 보니까, 0번째 원소만 10으로 바뀌었음을 볼 수 있습니다. 이로 미루어 보았을 때, setAll은 루프를 돌면서 generator의 평가식을 수행함을 볼 수 있습니다. 그렇기 때문에, new Obj(3);을 10번 호출하게 됩니다. 고로 필드 x의 값이 3인 오브젝트가 10개가 생성되게 됩니다. 별개의 object이므로, 한 개의 필드만 10으로 바꾸어도, 나머지는 영향을 미치지 않습니다.

 

 반면, fill은 이야기가 다릅니다. 결과가 어떻게 나올까요?

 

 모두 10이 나왔습니다. 객체의 참조값이 인자로 들어갑니다. 고로, 0번째 원소부터 9번째 원소까지 같은 객체의 참조값이 들어갑니다. 얕은 복사가 되어버리는 셈입니다. 이 차이점도 염두에 두면 좋겠습니다.