이번 시간에는 Collection에 있는 removeIf에 대해서 알아보겠습니다. 저는 보통 List에서 filtering을 걸어 제거할 때 쓰는 편이에요.

 


 먼저 predicate 인터페이스에요. 단어 사전을 보면, 근거를 두다, 단정하다 정도로 되어 있는데요. 앞에 a가 붙었으니 동사는 아닐 거 같네요. 서술? 이 정도로 해석하면 좋을까요? 술어? 이보다는 명제가 조금 더 적절하지 않을까 싶습니다. 그러면, 이 인터페이스는 어떠한 명제? 서술부가 참인지 거짓인지 판단하기 위해 쓰일 거 같아요.

 

 그러면, 사실인지 거짓인지 평가하는 메서드도 있을 거 아니에요?

 

 

 이것이 test에요. 이것은 인자 하나를 받아가지고 Evaluates, 평가를 하게 되는데요. 인풋으로 넘어온 인자가 predicate에 매치되면 참을 리턴하고, 아니면 거짓을 리턴해 버려요. ArrayList 안에서 removeIf가 어떻게 돌아가는지 코드 일부만 보겠습니다.

 

 

 415번째 줄을 보시면, filter.test(element)라고 되어 있는데요. element는 i번째에 있는 원소를 의미합니다. 다음에 filter가 문제인데요. 메인 클래스를 보면서 이야기 해 보도록 하겠습니다.

 

 

 main의 removeIf에 들어와 있는 술어는 k -> k%2 != 0입니다. 이 부분이 filter로 넘어온 건데요. 차근 차근 해석해 보도록 할게요.

 

 


 먼저, k -> k%2 != 0부터 보겠습니다.

 

 

 이것은 그냥 k 를 2로 나눈 나머지는 0이 아니다. 라는 술어입니다. test는 뭘까요? 인자 k를 넣어서, 술어가 참인지를 테스트 합니다.

 

 

 그림으로 그리면 이렇게 그려집니다. 예를 들어 k가 3이라면 3을 2로 나눈 나머지는 1이니까 T가 될 겁니다. 처음에 리스트에는 0, 3, 6, 9, 12, 15, 18, 21, 24, 27이 있었습니다. 이 리스트들을 쭉 돌면서 체크를 할 텐데요. filter.test(element)는 무엇을 의미할까요? filter에 들어온 술어는 k -> k%2 != 0이였으니, 인자로 넘어온 수에 2를 나누면 나머지가 0이 아니다. 라는 것이였습니다. 배열에 있는 원소들 중에서 이를 만족하는 것은 3, 9, 15, 21, 27입니다.

 

 

 이들이 filter.test에 걸려서 제거 되어야 할 원소에 들어가게 됩니다.

 

 

 따라서, 결과는 0, 6, 12, 18, 24가 나오게 됩니다. 즉, removeIf는 predicate로 넣은 술어 조건이 만족하는 원소에 대해서 모두 제거해 버리는 메서드입니다.

 

 


 여담으로 Collections에 쓸 수 있다고 해서, 모든 콜렉션에서 removeIf를 쓸 수 있는 것은 아닙니다. 본질적으로 removeIf는 조건을 만족할 때 해당 원소를 제거하는 것이므로 remove가 적용되지 않는 일부 Collection에 대해서는 쓰지 못 할 수도 있습니다. 예를 들어, 이 블로그에서 소개했던 nCopies를 보겠습니다.

 

 

 1이 5개 있는 리스트입니다. 이것은 remove와 같은 것이 Unsupported 되는 것 중 하나입니다. 이 프로그램을 실행해 보면, 떡하니 예외가 떠 버리는데요.

 

 

 예외 트레이스를 타고 가 보면, Unsupported 예외가 떴음을 볼 수 있어요. 이러한 점은 조심할 필요가 있겠네요.