- Published on
항해99 플러스 백엔드 코스 6기 언어 사전 스터디 2주차 (3) - 컬렉션
- Authors
- Name
- Kil Hyeon Jun
항해99 플러스 백엔드 코스 6기 언어 사전 스터디 2주차 - 컬렉션
소개
이번 2주차 스터디에서는 Java의 컬렉션에 대해 학습했다.
1. 컬렉션 프레임워크 (Collection Framework)
컬렉션 프레임워크란?
- 여러 객체를 효율적으로 관리하기 위한 자료구조와 알고리즘을 제공하는 프레임워크
- Java에서 제공하는
java.util
패키지의 인터페이스와 클래스로 구현
주요 인터페이스
Collection 인터페이스
객체의 집합을 나타내는 최상위 인터페이스
List, Set, Queue 인터페이스의 상위 인터페이스
List
: 순서가 있는 데이터의 집합을 나타내는 인터페이스Set
: 순서가 없고 중복을 허용하지 않는 데이터의 집합을 나타내는 인터페이스Queue
: 데이터를 임시로 저장해두는 큐 자료구조를 나타내는 인터페이스 (FIFO 방식)
Map 인터페이스
- 키와 값의 쌍으로 이루어진 데이터의 집합을 나타내는 인터페이스
- Collection 인터페이스를 직접 구현하지 않지만, 컬렉션 프레임워크의 일부
컬렉션과 Map의 관계
- Map은 Collection 인터페이스를 직접 구현하지 않지만, 컬렉션 프레임워크의 중요한 부분
- Map의 values() 메소드는 Collection을 반환하고, entrySet()과 keySet() 메소드는 Set을 반환하여 간접적으로 컬렉션과 연결됨
List 인터페이스
- 순서가 있는 데이터의 집합
- 중복을 허용
- 인덱스로 데이터에 접근 가능
ArrayList 클래스
- 가변 크기의 배열 구현
- 배열의 크기가 부족할 경우 자동으로 크기를 늘림
- 배열의 중간에 요소를 추가하거나 삭제할 경우 다른 요소들을 이동해야 함
- 데이터 조회가 빈번한 경우 유리
LinkedList 클래스
- 노드로 연결된 리스트 구현
- 요소를 추가하거나 삭제할 때 다음 요소의 주소를 변경하면 되므로 ArrayList보다 빠름
- 요소의 추가, 삭제가 빈번할 경우 유용
- 인덱스로 요소에 접근할 때는 처음부터 찾아야 하므로 느림
Stack 클래스
- LIFO(Last In First Out) 방식의 스택 자료구조 구현
push()
,pop()
,peek()
등의 메서드 제공
Queue 인터페이스
- FIFO(First In First Out) 방식의 큐 자료구조
LinkedList
클래스로 구현offer()
,poll()
,peek()
등의 메서드 제공
Set 인터페이스
- 순서가 없고 중복을 허용하지 않는 데이터의 집합
HashSet
,TreeSet
,LinkedHashSet
클래스로 구현
HashSet
- 해시 테이블을 사용한 집합 구현
- 가장 빠르며 순서를 전혀 예측할 수 없음
- 중복 제거에 효과적
TreeSet
- 이진 검색 트리를 사용한 집합 구현
- 정렬된 순서대로 보관하며 정렬 방법을 지정할 수 있음
- 정렬이 필요한 경우 유용
LinkedHashSet
- 해시 테이블과 연결 리스트를 사용한 집합 구현
- 추가된 순서, 또는 가장 최근에 접근한 순서대로 접근 가능
- 예측 가능한 반복 순서가 필요할 때 유용
Map 인터페이스
- 키와 값의 쌍으로 이루어진 데이터의 집합
- 키는 중복을 허용하지 않으며 값은 중복을 허용
HashMap
,TreeMap
,LinkedHashMap
클래스로 구현
HashMap
- 중복을 허용하지 않고 순서를 보장하지 않음
- 키와 값으로 null이 허용
- 가장 많이 사용되는 Map 구현체
TreeMap
- 키 값을 기준으로 정렬을 할 수 있음
- 저장 시 정렬(기본적으로 오름차순)을 하기 때문에 저장 시간이 다소 오래 걸림
- 정렬된 상태로 Map을 유지해야 할 때 유용
LinkedHashMap
- HashMap과 LinkedList의 특성을 결합
- 입력 순서나 최근 사용 순서대로 순회 가능
TIP
length
vs length()
vs size()
- 길이값 가져오기
- length
arrays(int[], double[], String[])length
는 배열의 길이를 조회한다. - length()
String related Object(String, StringBuilder etc)length()
는 문자열의 길이를 조회한다. (ex. "ABCD".length() == 4) - size()
Collection Object(ArrayList, Set etc)size()
는 컬렉션 타입목록의 길이를 조회한다.
2주차 숙제 - 자료구조 요리 레시피 메모장 만들기
프로그램 요구사항
- 입력값을 저장할 자료구조 선택하기 (List / Set / Map)
- 요리 제목 입력받기
- 요리 레시피를 한 문장씩 입력받기 (종료 조건: "끝" 입력)
- 입력받은 정보를 형식에 맞게 출력하기
주요 구현 포인트
Scanner
클래스를 사용하여 사용자 입력 받기- 선택한 자료구조(List, Set, Map)를 사용하여 레시피 저장하기
- 문자열 연산을 통해 출력 형식 맞추기 (자료구조명과 요리 제목 괄호로 감싸기)
- 레시피 각 문장에 번호 붙여 출력하기
구현 코드
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Scanner;
public class RecipeNotepad {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 저장할 자료구조명 입력 (List / Set / Map)
String dataStructure = sc.nextLine();
// 요리 제목 입력
String recipeTitle = sc.nextLine();
// 자료 구조 선언
var recipes = createDataStructure(dataStructure);
// 레시피 입력
while (true) {
String recipe = sc.nextLine();
if (recipe.equals("끝")) {
break;
}
addRecipe(recipes, recipe);
}
// 레시피 출력
String recipeContent = getRecipeContent(recipes);
System.out.printf("[ %s 으로 저장된 %s ] \n", dataStructure, recipeTitle);
System.out.println(recipeContent);
}
private static Object createDataStructure(String dataStructure) {
switch (dataStructure.toUpperCase()) {
case "LIST":
return new ArrayList<String>();
case "SET":
return new LinkedHashSet<String>();
case "MAP":
return new LinkedHashMap<String, String>();
default:
throw new IllegalArgumentException("지원하지 않는 자료구조입니다.");
}
}
private static void addRecipe(Object recipes, String recipe) {
if (recipes instanceof ArrayList) {
((ArrayList<String>) recipes).add(recipe);
} else if (recipes instanceof LinkedHashSet) {
((LinkedHashSet<String>) recipes).add(recipe);
} else if (recipes instanceof LinkedHashMap) {
((LinkedHashMap<Integer, String>) recipes).put(
((LinkedHashMap<String, String>) recipes).size(), recipe);
}
}
private static String getRecipeContent(Object recipes) {
StringBuilder sb = new StringBuilder();
int i = 1;
Collection<String> recipeCollection;
if (recipes instanceof ArrayList) {
recipeCollection = (ArrayList<String>) recipes;
} else if (recipes instanceof LinkedHashSet) {
recipeCollection = (LinkedHashSet<String>) recipes;
} else if (recipes instanceof LinkedHashMap) {
recipeCollection = ((LinkedHashMap<String, String>) recipes).values();
} else {
throw new IllegalArgumentException("지원하지 않는 자료구조입니다.");
}
for (String recipe : recipeCollection) {
sb.append(i++).append(". ").append(recipe).append("\n");
}
return sb.toString();
}
}
NOTE
이 예제의 코드는 Object 타입을 사용하여 다형성을 활용하였다.
다형성을 사용하면 코드의 유연성을 높일 수 있으나, 타입 캐스팅이 필요하므로 주의해야 한다.
인터페이스를 사용한 다향성으로 리펙토링할 수도 있을 것 같다.
결론
2주차에선 Java의 연산자, 조건문, 반복문, 배열, 컬렉션에 대해 학습했다.
해당 주차에서 컬렉션에 대해 학습하며, 배열과 컬렉션의 차이점을 이해할 수 있었다.
컬렉션은 배열과 달리 크기가 가변적이며, 여러 객체를 모아놓은 것이라는 점을 알 수 있었다.
컬렉션은 java.util
패키지의 인터페이스와 클래스로 구현되며, List
, Set
, Map
, Queue
인터페이스가 있다.
각 인터페이스는 다양한 클래스로 구현되며, 각 클래스는 특징과 사용 용도가 다르다.
컬렉션을 사용하면 데이터를 효율적으로 관리할 수 있으며, 다양한 자료구조를 활용할 수 있다.
본문에 다룬 컬렉션 클랙스 외에도 다양한 컬렉션 클래스가 존재하므로 추후 학습이 필요할 것 같다.