컬렉션 API
- 컬렉션 프레임워크
- List
- Map
- Set
발표자 : 박세종
발표 내용 + 부연설명
🔍 왜 컬렉션 프레임워크를 사용할까?
컬렉션 프레임워크란
- 여러 개의 데이터를 저장 및 표현이 가능한 클래스들의 집합
- 표준화된 인터페이스를 제공
- 각 구현체들이 어떻게 구성되어있는지에 신경 쓸 필요 없음
- 필요(성능)에 따라서 구현체를 선택가능
컬렉션 프레임워크 대표 3가지
- List<E>
- 순서대로 데이터를 저장할 수 있어야 한다. (중복 가능)
- 일반 적으로 가장 많이 사용
- Set<E>
- 데이터를 중복 없이 저장할 수 있어야 한다.
- 유일한 데이터를 담을 수 있다.
- Map<K, V>
- 키와 값을 한쌍으로 데이터를 저장하는 경우
- 키의 경우 중복을 허용하지 않는다.
👆 List<E> : 순서대로 데이터가 들어가야 한다. (중복 가능)
- get : 특정 인덱스의 데이터를 반환한다.
- add : 데이터를 추가한다. (인덱스 지정 가능)
- remove : 데이터를 삭제한다. (인덱스 혹은 데이터 지정가능)
- size: 아이템 개수를 반환
- contains: 특정 데이터가 존재하는지 여부 반환
✌ Set<E> : 데이터를 중복 없이 저장할 수 있어야 한다.
- add : 데이터를 추가한다.
- remove : 데이터를 삭제한다.
- size: 아이템 개수를 반환
- contains: 특정 요소가 존재하는지 여부 반환
👌 Map<K, V> : 키와 값을 한쌍으로 데이터를 저장하는 경우
- put : 키와 값 추가한다.
- remove : 키를 기준으로 값을 삭제한다.
- size: 데이터 개수를 반환
- containsKey: 특정키가 존재하는지 여부 반환
- containsValue: 특정 데이터가 존재하는지 여부 반환
실습 문제 1번
정수 배열에서 중복 값을 제거 후 오름차순으로 정렬하여 출력하시오
[5,2,7,1,2] 인 경우 [1,2,5,7]로 출력
실습 문제 2번
정수 값이 저장된 리스트가 있다.
각 정수들이 몇 개가 존재하는지를 찾고 출력해보자 (Map을 이용해보자)
ex) [1,2,1,4,2,1] :: 1=>3개, 2=>2개 4=>1개
풀이 1
public class CollectionExercise01 {
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<>(asList(5, 2, 7, 1, 2));
// 중복제거
Set<Integer> eraseSet = new HashSet<>(numbers);
ArrayList<Integer> newNembers = new ArrayList<>(eraseSet);
// 정렬
Collections.sort(newNembers);
System.out.println(newNembers);
}
}
풀이 1-1
public class CollectionExercise01 {
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<>(asList(5, 2, 7, 1, 2));
List<Integer> collect = numbers.stream()
.distinct()
.sorted()
.collect(Collectors.toList());
System.out.println(collect);
}
}
풀이 2
public class CollectionExercise02 {
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<>(asList(1, 2, 1, 4, 2, 1));
Map<Integer, Integer> resultMap = new HashMap<>();
for(int number : numbers) {
if(!resultMap.containsKey(number)) {
resultMap.put(number, 0); // 없으면 초기값 0
}
resultMap.put(number, (resultMap.get(number) + 1));
}
System.out.println(resultMap);
}
}
풀이 2-1
public class CollectionExercise02 {
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<>(asList(1, 2, 1, 4, 2, 1));
// 출력 1
System.out.println(
numbers.stream().collect(Collectors.groupingBy(key -> key, Collectors.counting())));
// 출력 2
System.out.println(
numbers.stream().collect(Collectors.groupingBy(key -> key, Collectors.toList())));
}
}
출력 결과
풀이 2-2 (스터디원 풀이)
getOrDefault() - 값이 있으면 데이터를 넣고 없으면 default값을 넣는 함수
public class CollectionExcercise02_1 {
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<>(asList(1, 2, 1, 4, 2, 1));
Map<Integer, Integer> map = new HashMap();
for(int number : numbers) {
map.put(number, map.getOrDefault(number, 0)+ 1);
}
System.out.println(map);
}
}
List(리스트) 생성 방법 3가지
public static void main(String[] args) {
// java 8 이하
List<String> list1 = Arrays.asList("Java", "Kotlin", "C++");
// java 9 이상
List<String> list2 = List.of("Java", "Kotlin", "C++");
// stream 이용
List<String> list3 = Stream.of("AAA", "BBB", "CCC").collect(toList());
System.out.println(list1);
System.out.println(list2);
System.out.println(list3);
}
Set 생성 방법 3가지
// 자바 8 이하
HashSet set1 = new HashSet(Arrays.asList("JAVA", "KOTLIN", "C++"));
// 자바 9 이상
Set<String> set2 = Set.of("JAVA", "KOTLIN", "C++");
// stream 이용
Set<String> set3 = Stream.of("JAVA", "KOTLIN").collect(Collectors.toSet());
System.out.println(set1);
System.out.println(set2);
System.out.println(set3);
Map.of
Map<Integer, String> map1 = Map.of(1, "Aaa", 2, "Bbb");
System.out.println(map1);
- List<E> : 순서대로 데이터를 저장할 수 있어야 한다. (중복가능)
- ArrayList, LinkedList,
- Set<E> : 데이터를 중복없이 저장할 수 있어야 한다. (순서 보장 x)
- HashSet, TreeSet
- Map<K, V> : 키와 데이터를 한쌍으로 데이터를 저장하여야 한다.
- HashMap, LinkedHashMap, TreeMap
ArrayList
- 가장 많이 사용되는 List의 구현체
- 배열을 기반으로 데이터를 저장
- 장점 : 순차적인 데이터 추가/삭제/조회 빠름
- 단점 : 중간의 데이터 추가/삭제는 배열 복사가 필요(속도가 느림)
LinkedList
- 각 노드들은 다음 노드가 무엇인지를 저장
- 노드들의 링크를 통해서 리스트를 구성
- 장점 : 저장/삭제가 빈번한 경우 유리(빠름)
- 단점 : 특정 위치의 값을 가져오는 작업에선 불리함(처음부터 순차적으로 찾아야 함)
equals & hashcode
- 객체의 동일함을 비교할 수 있는 메서드
- Object에 기본적으로 설정되어있지만..
- 객체 자체의 값을 기준으로 동일함을 제대로 알려주기 위해서는
- equals와 hashcode를 오버 라이딩하여야 하여야 함
- 왜 두 개일까??
- hashcode > 결과 값이 int로 반환되어 단순. 하지만 충돌 가능성을 내포..
- equals > 정확하게 비교 가능(정말 같은지 비교)
equals와 hashcode는 IDE를 통해 자동완성할 수 있지만 클래스 변수가 새로 추가되면 다시 만들어야 한다.
자바 15에서는 record를 통해서 좀 더 편하게 할 수 있으며, 롬복을 이용해서 @EqualsAndHashCode를 사용하면 편리하다.
HashMap
- key / value 형태로 데이터를 저장
- 키를 해싱하여 저장
- 키를 이용, 데이터에 빠르게 접근 가능
- 데이터가 계속 추가되면.. 느려요
- 초기 사이즈 지정으로 성능 이슈 줄일 수 있음
- 키에 대한 순서 자체에 대한 보장이 되지 않는다.
LinkedHashMap
- 해시맵과 기본적으로 동일
- 엔트리들끼리 링크로 연결
- 키를 순서대로 저장하고 가져오는데 유리 (키에 대한 순서를 보장 한다.)
HashSet
- HashMap을 내부적으로 이용
- HashMap<E, ?>
- 원하는 요소에 빠르게 접근가능
- 만약 정렬이 필요하다면..
- TreeSet을 이용하자
이외에도..
- 동시성이 필요한 환경에서
- ConcurrentHashMap
- CopyOnWriteArrayList
- 동시성 이란? 하나의 객체에 여러 개의 스레드가 한번에 접근하는 경우를 생각
- 톰캣은 200개 스레드가 돌고 있다.
- 극단적인 환경인 경우 동시성 보장이 필요한 경우에 사용한다.
- Queue
- 입력한 순서대로 데이터 꺼내야 하는 경우
- Stack
- 마지막에 저장한 데이터를 가장 먼저 꺼내야 하는 경우
null보다는 empty를 이용하자..
- 컬렉션의 경우 값이 존재하지 않는다를 두 가지로 표현 가능.
- null or empty
- 비어있다를 emptyList로 표현해주면 사용하는 좀 더 편하게 사용 가능
- Collections.emptyList / Collections.emptyMap / Collections.emptySet을 사용하거나
- List<String> list = new ArrayList(); 처럼 비워 놓자
웬만해서는 불변으로 만들자
- A객체가 List를 만들고, B객체에게 넘겨줌
- B는 데이터를 일부 삭제함
- A는 삭제된 데이터 때문에 버그 발생
- 왠만해서는 변경 불가능하게 막자.
- kotlin으로??
- 알 수 없는 버그는 원천 차단해 버리자.
final은 할당 후 변경이 불가능한 것이다. 안에 있는 객체까지 변경되는 것을 막지는 못한다.
예를 들면 private final List<String> products;
해결 : Collections.unmodifiableList(products);를 사용하자
조금 더 고급지게 사용하기(컬렉션을 더 쉽게 다룰 수 있는 도구들)
- 하위 호환 등의 이유로 확장이 쉽지 않음
- defaultMethod로 조금씩 확장 중
- java8 stream API
- 8주 차를 기대해주세요
- guava collection
- BiMap(키밸류 가 아닌, 양쪽 다 키로 사용하는 겨우)
- MultiSet, MultiMap
- eclipse collection
- 이클립스 재단에서 만든 컬렉션
- 자바에서 있는 컬렉션보다 빠르다.
'Java > JavaCafe Study' 카테고리의 다른 글
5주차 코드 효율성 (0) | 2021.07.11 |
---|---|
3주차 객체지향 (0) | 2021.06.05 |
2주차 JAVA API (0) | 2021.05.30 |