728x90
개요
ArrayList<String> arrayList = new ArrayList<>();
HashSet<String> hashSet = new HashSet<>();
HashMap<String, Integer> hashMap = new HashMap<>();
Java에서 컬렉션을 사용할 때 위와 같이 구현체로 직접 선언하는 경우가 있습니다. 하지만 실제로는 인터페이스를 사용해 선언하는 것이 더 좋은 방법입니다.
List<String> list = new ArrayList<>();
Set<String> set = new HashSet<>();
Map<String, Integer> map = new HashMap<>();
본 글에서는 이러한 차이점과 인터페이스를 사용해 선언해야 하는 이유에 대해 정리하고자 합니다.
주요 컬렉션 인터페이스와 구현체
1. List 인터페이스
List<String> list = new ArrayList<>(); // 인터페이스로 선언
List<String> linkedList = new LinkedList<>(); // 구현체만 변경
- 순서가 있는 데이터의 집합
- 주요 구현체:
- ArrayList: 내부적으로 배열을 사용, 조회가 빠름
- LinkedList: 이중 연결 리스트, 삽입/삭제가 빠름
2. Set 인터페이스
Set<String> set = new HashSet<>(); // 인터페이스로 선언
Set<String> treeSet = new TreeSet<>(); // 정렬이 필요할 때
중복을 허용하지않는 데이터의 집합- 주요 구현체:
- HashSet: 해시 테이블을 사용, 정렬되지 않음
- TreeSet: 이진 검색 트리를 사용, 자동 정렬됨
3. Map 인터페이스
Map<String, Integer> map = new HashMap<>(); // 인터페이스로 선언
Map<String, Integer> treeMap = new TreeMap<>(); // 키 기준 정렬 필요시
- 키-값 쌍의 데이터 집합
- 주요 구현체:
- HashMap: 해시 테이블을 사용, 정렬되지 않음
- TreeMap: 이진 검색 트리를 사용, 키 기준 정렬
인터페이스로 선언하는 것이 좋은 이유
1. 유연성 확보
- 코드 변경이 필요할 때 구현체만 변경하면 됩니다.
List<String> list = new LinkedList<>(); // ArrayList에서 LinkedList로 쉽게 변경 가능
- 예를 들어 ArrayList에서 LinkedList로 변경이 필요한 경우:
2. 다형성 활용
public void processItems(List<String> items) { // ArrayList, LinkedList 등 모든 List 구현체 가능
// 처리 로직
}
- 메소드의 매개변수로 List를 사용하면 어떤 List 구현체든 받을 수 있습니다.
3. 객체지향 설계 원칙 준수
- 구체적인 구현보다는 추상화에 의존하는 것이 좋습니다
- 이는 SOLID원칙 중 "의존성 역전 원칙(DIP)"을 따르는 것입니다
구현체로 선언해야 하는 경우
다음과 같은 경우에는 구현체를 직접 사용하는 것이 적절할 수 있습니다:
- 구현체의 고유한 메소드를 사용해야 하는 경우
- 성능상의 이유로 특정 구현체임을 명시해야 하는 경우
결론
특별한 이유가 없다면 컬렉션 프레임워크 사용 시 인터페이스로 선언하는 것이 좋습니다.
이는 코드의 유연성을 높이고, 객체지향적인 설계를 가능하게 합니다. 다만 구현체의 특정 기능이 필요한 경우에는 구현체로 직접 선언하는 것이 적절할 수 있습니다.