Java의 List 인터페이스는 두 리스트를 비교하여 공통 항목과 누락된 항목을 손쉽게 찾을 수 있는 다양한 메서드를 제공합니다. 이 글에서는 equals(), removeAll(), retainAll() 메서드를 활용해 두 리스트를 비교하는 방법을 예제 코드와 함께 살펴보겠습니다.
정렬되지 않은 두 리스트의 동일성 비교
두 리스트가 동일한지, 즉 같은 요소들을 같은 위치(인덱스)에 담고 있는지 확인하려면 equals() 메서드를 사용하면 됩니다.
import java.util.Arrays;
import java.util.List;
public class CompareTwoLists {
public static void main(String[] args) {
List<String> listOne = Arrays.asList("a", "b", "c");
List<String> listTwo = Arrays.asList("a", "b", "c");
List<String> listThree = Arrays.asList("c", "a", "b");
boolean isEqual = listOne.equals(listTwo);
System.out.println(isEqual);
isEqual = listOne.equals(listThree);
System.out.println(isEqual);
}
}
실행 결과:
true
false
위 결과에서 볼 수 있듯이 equals() 메서드는 요소의 값뿐만 아니라 리스트 내에서의 위치까지 함께 비교합니다. 따라서 구성 요소는 같지만 순서가 다른 listThree와 비교했을 때는 false가 반환됩니다.
- Java에서 ArrayList 순회하는 방법
- 리스트에서 중복 제거하는 방법
- Java에서 리스트를 배열로 변환하는 방법
정렬 후 두 리스트 비교하기
"두 리스트에 같은 요소들이 들어 있는가?"라는 질문에 답하려면 어떻게 해야 할까요?
요소의 위치와 상관없이 구성 요소만으로 두 리스트의 동일 여부를 판단하려면, Collections 클래스의 sort() 메서드로 두 리스트를 먼저 정렬한 뒤 비교해야 합니다.
예를 들어 다음과 같습니다:
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class CompareTwoLists {
public static void main(String[] args) {
List<String> listOne = Arrays.asList("b", "c", "a");
List<String> listTwo = Arrays.asList("a", "c", "b");
List<String> listThree = Arrays.asList("c", "a", "b");
Collections.sort(listOne);
Collections.sort(listTwo);
Collections.sort(listThree);
boolean isEqual = listOne.equals(listTwo);
System.out.println(isEqual);
isEqual = listOne.equals(listThree);
System.out.println(isEqual);
}
}
실행 결과:
true
true
두 리스트를 비교하여 차이점 찾기
List 인터페이스는 두 리스트 간의 차이점을 찾는 기능도 제공합니다.
removeAll() 메서드는 두 리스트를 비교하여 공통 요소를 모두 제거합니다. 그 결과 남는 요소는 한쪽 리스트에만 존재하는, 즉 추가되었거나 누락된 항목입니다.
예를 들어 listOne과 listTwo를 비교할 때, listTwo에 없는 요소가 무엇인지 알고 싶다면 다음과 같이 작성합니다:
import java.util.ArrayList;
import java.util.Arrays;
public class CompareTwoArrayLists {
public static void main(String[] args) {
ArrayList<Integer> listOne = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
ArrayList<Integer> listTwo = new ArrayList<>(Arrays.asList(1, 2, 4, 5, 6, 7));
listOne.removeAll(listTwo);
System.out.println("Missing items from listTwo " + listOne);
}
}
실행 결과:
Missing items from listTwo [3]
반대로 다음과 같이 호출하면:
listTwo.removeAll(listOne);
System.out.println("Missing items from listOne " + listTwo);
다음과 같은 결과를 얻습니다:
Missing items from listOne [6, 7]
두 리스트를 비교하여 공통 항목 찾기
retainAll() 메서드는 두 리스트에 공통으로 존재하는 요소만 남기고 나머지는 모두 제거합니다. 예를 들어:
public class CompareTwoArrayLists {
public static void main(String[] args) {
ArrayList<Integer> listOne = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
ArrayList<Integer> listTwo = new ArrayList<>(Arrays.asList(1, 2, 4, 5, 6, 7));
listOne.retainAll(listTwo);
System.out.println("Common items in both lists " + listOne);
}
}
실행 결과:
Common items in both lists [1, 2, 4, 5]
마무리 정리
각 메서드의 용도를 요약하면 다음과 같습니다.
- equals(): 요소와 순서가 모두 같은지 비교
- Collections.sort() + equals(): 순서와 무관하게 요소 구성이 같은지 비교
- removeAll(): 한쪽 리스트에만 있는 요소(차집합) 추출
- retainAll(): 두 리스트에 공통으로 있는 요소(교집합) 추출
주의할 점은, Arrays.asList()로 생성한 리스트는 고정 크기 리스트이므로 removeAll()이나 retainAll()을 직접 호출하면 UnsupportedOperationException이 발생할 수 있다는 것입니다. 이런 변경 연산이 필요하다면 위 예제처럼 new ArrayList<>(Arrays.asList(...)) 형태로 새로운 리스트를 만들어 사용하는 것이 안전합니다.