-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[모던 자바 인 액션] 4주차 #6
Comments
자바 8, 9 - 컬렉션 API 개선1. 컬렉션 팩토리1-1. List 팩토리
@DisplayName("List 팩토리 사용")
@Test
void list_factory_test() {
List<String> coffeeList = List.of("메가커피", "스타벅스", "빽다방");
System.out.println("coffeeList = " + coffeeList);
}
// 결과
coffeeList = [메가커피, 스타벅스, 빽다방] 1-2. Set 팩토리
@DisplayName("Set 팩토리 사용")
@Test
void set_factory_test() {
Set<String> coffeeSet = Set.of("메가커피", "스타벅스", "빽다방");
System.out.println("coffeeSet = " + coffeeSet);
}
// 결과
coffeeSet = [메가커피, 빽다방, 스타벅스] 1-3. Map 팩토리
@DisplayName("Map 팩토리 사용")
@Test
void map_factory_test() {
Map<String, Integer> coffeeOfMap = Map.of("메가커리", 1500, "스타벅스", 3500, "백다방", 2000);
Map<String, Integer> coffeOfEntiriesMap = Map.ofEntries(
Map.entry("메가커리", 1500),
Map.entry("스타벅스", 3500),
Map.entry("백다방", 2000)
);
System.out.println("coffeeOfMap = " + coffeeOfMap);
System.out.println("coffeOfEntiriesMap = " + coffeOfEntiriesMap);
}
// 결과
coffeeOfMap = {스타벅스=3500, 백다방=2000, 메가커리=1500}
coffeOfEntiriesMap = {스타벅스=3500, 백다방=2000, 메가커리=1500} 열 개 이하의 key와 value를 가진 작은 크기의 Map을 만들 때는 1-4. 주의사항
컬렉션 팩토리로 만들어진 컬렉션에 추가, 삭제, 변경 시 @DisplayName("팩토리로 만들어진 컬렉션에 추가 시 예외")
@Test
void list_factory_ex_test1() {
List<String> coffeeList = List.of("메가커피", "스타벅스", "빽다방");
assertThrows(UnsupportedOperationException.class, () -> coffeeList.add("이디야"));
}
@DisplayName("팩토리로 만들어진 컬렉션에 요소 삭제 시 예외")
@Test
void list_factory_ex_test2() {
List<String> coffeeList = List.of("메가커피", "스타벅스", "빽다방");
assertThrows(UnsupportedOperationException.class, () -> coffeeList.remove("스타벅스"));
}
@DisplayName("팩토리로 만들어진 컬렉션에 요소 수정 시 예외")
@Test
void list_factory_ex_test3() {
List<String> coffeeList = List.of("메가커피", "스타벅스", "빽다방");
assertThrows(UnsupportedOperationException.class, () -> coffeeList.set(1, "이디야"));
} 두 번째로 컬렉션 팩토리의 파라미터로 전달한 요소들이 null이면 @DisplayName("팩토리의 파라미터로 null을 전달 시 예외")
@Test
void list_factory_ex_test4() {
assertThrows(NullPointerException.class, () -> List.of("메가커피", "스타벅스", "빽다방", null));
} 세 번째로는 컬렉션에서 제공하는 메서들 또한 파라미터의 값이 null 일 경우 @DisplayName("컬렉션에서 제공하는 메서드의 파라미터로 null을 전달 시 예외")
@Test
void list_factory_ex_test5() {
List<String> coffeeList = List.of("메가커피", "스타벅스", "빽다방");
assertThrows(NullPointerException.class, () -> coffeeList.contains(null));
} 2. List와 Set에 추가된 메서드2-1. removeIf(Predicate<? super E> filter) Predicate에 만족하는 요소들을 제거하며 List나 Set을 상속받은 모든 클래스에서 사용할 수 있다. 아래 예시 코드는 자바 9 이전에는 어떻게 제거했는지와 현재 자바 9 버전 이상에서 사용되는 @DisplayName("리스트 컬렉션의 removeIf")
@Test
void list_removeIf() {
// ** 자바 9 이전 코드 **
// List의 특정 요소 제거
List<String> coffeeList1 = new ArrayList<>();
coffeeList1.add("메거커피");
coffeeList1.add("스타벅스");
coffeeList1.add("빽다방");
for (String s : coffeeList1) {
if (s.equals("스타벅스")) {
coffeeList1.remove("스타벅스");
}
}
assertThat(coffeeList1.size()).isEqualTo(2);
assertThat(coffeeList1).isNotEqualTo("스타벅스");
// ** 자바 9 이후 코드 **
// List의 특정 요소 제거
List<String> coffeeList2 = new ArrayList<>();
coffeeList2.add("메거커피");
coffeeList2.add("스타벅스");
coffeeList2.add("빽다방");
coffeeList2.removeIf(name -> name.equals("스타벅스"));
assertThat(coffeeList2.size()).isEqualTo(2);
assertThat(coffeeList2).isNotEqualTo("스타벅스");
} 2-2. replaceAll(UnaryOperator operator) List에서 추가된 기능으로 @Test
void list_replaceAll() {
List<String> coffeeList = new ArrayList<>();
coffeeList.add("메가커피");
coffeeList.add("스타벅스");
coffeeList.add("빽다방");
coffeeList.replaceAll(coffee -> coffee + " 가맹점");
System.out.println("coffeeList = " + coffeeList);
}
// 결과
coffeeList = [메가커피 가맹점, 스타벅스 가맹점, 빽다방 가맹점] Stream을 이용해도 각 요소를 새로운 요소로 변경할 수 있지만 Stream은 새로운 컬렉션을 만들기 때문에 불필요한 자원낭비의 원인이 된다. 따라서 Stream을 사용해야 될 이유가 없으면 3. Map 관련 메서드3-1. forEach(BiConsumer<? super K, ? super V> action) Map에서도 @DisplayName("Map forEach 메서드 사용하기 이전 코드")
@Test
void map_for_each() {
Map<String, Integer> coffeeMap = new HashMap<>();
coffeeMap.put("메가커피", 2000);
coffeeMap.put("스타벅스", 3500);
coffeeMap.put("빽다방", 2000);
for (Map.Entry<String, Integer> entry : coffeeMap.entrySet()) {
String coffee = entry.getKey();
Integer price = entry.getValue();
System.out.println("coffeeMap = " + coffee + ":" + price);
}
}
@DisplayName("Map forEach 메서드를 사용한 코드")
@Test
void map_forEach() {
Map<String, Integer> coffeeMap = new HashMap<>();
coffeeMap.put("메가커피", 2000);
coffeeMap.put("스타벅스", 3500);
coffeeMap.put("빽다방", 2000);
coffeeMap.forEach((coffee, price) -> System.out.println("coffeeMap = " + coffee + ":" + price));
}
// 결과
coffeeMap = 빽다방:2000
coffeeMap = 메가커피:2000
coffeeMap = 스타벅스:3500 3-2. 정렬 메서드Map에서는 두 개의 새로운 유틸리티를 사용하여 key 또는 value를 기준으로 정렬할 수 있다. Entry.comparingByKey @DisplayName("Map key, value 중심으로 정렬")
@Test
void map_comparing_by_key() {
Map<String, Integer> coffeeMap = new HashMap<>();
coffeeMap.put("메가커피", 2000);
coffeeMap.put("스타벅스", 3500);
coffeeMap.put("빽다방", 2100);
// 기존 정렬 순서
System.out.println("coffeeMap = " + coffeeMap);
// key 기준으로 정렬
coffeeMap.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.forEachOrdered(System.out::println);
}
// 결과
메가커피=2000
빽다방=2100
스타벅스=3500 Entry.comparingByValue @DisplayName("Map key, value 중심으로 정렬")
@Test
void map_comparing_by_key() {
Map<String, Integer> coffeeMap = new HashMap<>();
coffeeMap.put("메가커피", 2000);
coffeeMap.put("스타벅스", 3500);
coffeeMap.put("빽다방", 2100);
// 기존 정렬 순서
System.out.println("coffeeMap = " + coffeeMap);
// value 기준으로 정렬
coffeeMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue())
.forEachOrdered(System.out::println);
}
// 결과
메가커피=2000
빽다방=2100
스타벅스=3500 3-3. getOrDefault 메서드 이전에는 Map에 해당하는 key가 존재하지 않으면 null이 반환되므로 첫 번째 인수를 key값을 받고, 두 번째는 Map에 해당 key가 없을 경우 반환하는 인수를 받는다. @DisplayName("Map - getOrDefault 메서드")
@Test
void map_getOrDefault_test() {
Map<String, Integer> coffeeMap = new HashMap<>();
coffeeMap.put("메가커피", 2000);
coffeeMap.put("스타벅스", 3500);
coffeeMap.put("빽다방", 2100);
// Map key에 메가커피가 있으므로 2000이 반환된다.
Integer megaCoffePrice = coffeeMap.getOrDefault("메가커피", 1500);
System.out.println("megaCoffePrice = " + megaCoffePrice);
// Map key에 이디야가 없으므로 두 번째 인수로 받은 값인 3200이 반환된다.
Integer ediyaPrice = coffeeMap.getOrDefault("이디야", 3200);
System.out.println("ediyaPrice = " + ediyaPrice);
// getOrDefault 를 사용하지 않은 코드는 다음과 같다.
Integer ediyaPriceByGet = coffeeMap.get("이디야");
if (ObjectUtils.isEmpty(ediyaPriceByGet)) {
ediyaPriceByGet = 3200;
}
System.out.println("ediyaPriceByGet = " + ediyaPriceByGet);
}
// 결과
megaCoffePrice = 2000
ediyaPrice = 3200
ediyaPriceByGet = 3200 3-4. 계산 관련 메서드Map에 키가 존재하지는 여부에 따라 특정 동작을 실행하고 결과를 저장해야 하는 상황이 필요한 경우가 많다. Map에는 이러한 연산을 도와주는 세 가지 메서드가 존재한다. computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) key에 해당되는 값이 없으면 Map에 추가해 주는 메서드이다. 첫 번째 인자로 key를 받고, 두 번째 인자로는 첫 번째 인자로 받은 key에 해당되는 값이 Map에 없을 경우 value 값을 생성하여 추가해 준다. @DisplayName("Map - 계산 관련 메서드")
@Test
void map_computeIfAbsent() {
Map<String, Integer> coffeeMap = new HahMap<>();
coffeeMap.put("메가커피", 2000);
coffeeMap.put("스타벅스", 3500);
coffeeMap.put("빽다방", 2100);
// key(이디야)가 Map에 없으므로 Map에 추가해준다.
// coffeeMap.put("이디야", 3200) 실행
coffeeMap.computeIfAbsent("이디야", coffee -> 3200);
System.out.println("coffeeMap = " + coffeeMap);
}
// 결과
coffeeMap = {빽다방=2100, 메가커피=2000, 스타벅스=3500, 이디야=3200} computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) key에 해당되는 값이 Map 존재하며 value 값이 null이 아닌 경우에만 새로운 value를 넣어주는 메서드이다. @DisplayName("Map - 계산 관련 메서드3")
@Test
void map_computeIfPresent1() {
Map<String, List<Integer>> coffeeMap = new HashMap<>();
coffeeMap.put("메가커피", new ArrayList<>());
coffeeMap.put("스타벅스", null);
coffeeMap.put("빽다방", new ArrayList<>());
List<Integer> addList = new ArrayList<>();
addList.add(2000);
addList.add(3000);
// 메가커피의 value가 null이 아니므로 addList가 추가된다.
coffeeMap.computeIfPresent("메가커피", (coffee, price) -> addList);
// 스타벅스의 value가 null이므로 해당 메서드는 실행되지 않는다.
coffeeMap.computeIfPresent("스타벅스", (coffee, price) -> addList);
System.out.println("coffeeMap = " + coffeeMap);
}
// 결과
coffeeMap = {빽다방=[], 메가커피=[2000, 3000], 스타벅스=null} compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) @DisplayName("Map - 계산 관련 메서드4")
@Test
void map_compute1() {
Map<String, List<Integer>> coffeeMap = new HashMap<>();
coffeeMap.put("메가커피", new ArrayList<>());
coffeeMap.put("스타벅스", null);
coffeeMap.put("빽다방", new ArrayList<>());
List<Integer> addList = new ArrayList<>();
addList.add(2000);
addList.add(3000);
// 실행 된다.
coffeeMap.compute("메가커피", (coffee, price) -> addList);
// 실행 된다.
coffeeMap.compute("스타벅스", (coffee, price) -> addList);
System.out.println("coffeeMap = " + coffeeMap);
}
// 결과
coffeeMap = {빽다방=[], 메가커피=[2000, 3000], 스타벅스=[2000, 3000]} 3-5. remove(key), remove(key, value) Map 역시 remove 메서드를 통해 해당되는 값을 Map에서 제거할 수 있다. 인자로 key만 받는 @DisplayName("Map - remove")
@Test
void map_remove() {
Map<String, Integer> coffeeMap = new HashMap<>();
coffeeMap.put("메가커피", 2000);
coffeeMap.put("스타벅스", 3500);
coffeeMap.put("빽다방", 2100);
// 메가커피 key가 존재하므로 제거
coffeeMap.remove("메가커피");
// 스타벅스 key가 존재하고, value 값이 동일하므로 제거
coffeeMap.remove("스타벅스", 3500);
// 빽다방 key가 존재하지만 value 값이 동일하지 않으므로 제거되지 않는다.
coffeeMap.remove("빽다방", 2200);
System.out.println("coffeeMap = " + coffeeMap);
}
// 결과
coffeeMap = {빽다방=2100} 3-6. replaceAll(BiFunction<? super K, ? super V, ? extends V> function)List에서 사용했던 메서드와 비슷하다. BiFunction에 적용된 결과로 각 항목의 값을 변경한다. @DisplayName("Map - replaceAll")
@Test
void map_replaceAll() {
Map<String, Integer> coffeeMap = new HashMap<>();
coffeeMap.put("메가커피", 2000);
coffeeMap.put("스타벅스", 3500);
coffeeMap.put("빽다방", 2100);
coffeeMap.replaceAll((coffee, price) -> price + 500);
System.out.println("coffeeMap = " + coffeeMap);
}
// 결과
coffeeMap = {빽다방=2600, 메가커피=2500, 스타벅스=4000} 3-7. replace(K key, V value), replace(K key, V oldValue, V newValue) 키가 존재하면 해당되는 값을 변경한다. @DisplayName("Map - replace")
@Test
void map_replace() {
Map<String, Integer> coffeeMap = new HashMap<>();
coffeeMap.put("메가커피", 2000);
coffeeMap.put("스타벅스", 3500);
coffeeMap.put("빽다방", 2100);
// 메가커피인 key를 찾아 value를 2500으로 변경
coffeeMap.replace("메가커피", 2500);
System.out.println("coffeeMap = " + coffeeMap);
// 스타벅스인 key를 찾아 value가 3000인 경우 4000으로 변경
// oldValue가 3000이기 때문에 실행되지 않는다.
coffeeMap.replace("스타벅스", 3000, 4000);
System.out.println("coffeeMap = " + coffeeMap);
// 스타벅스인 key를 찾아 value가 3000인 경우 4000으로 변경
// value가 3500이기 때문에 실행된다.
coffeeMap.replace("스타벅스", 3500, 4000);
System.out.println("coffeeMap = " + coffeeMap);
}
// 결과
coffeeMap = {빽다방=2100, 메가커피=2500, 스타벅스=3500}
coffeeMap = {빽다방=2100, 메가커피=2500, 스타벅스=3500}
coffeeMap = {빽다방=2100, 메가커피=2500, 스타벅스=4000} 3-8. merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) @DisplayName("Map - merge")
@Test
void map_merge() {
Map<String, List<Integer>> coffeeMap = new HashMap<>();
coffeeMap.put("메가커피", new ArrayList<>());
coffeeMap.get("메가커피").add(2000);
coffeeMap.put("스타벅스", new ArrayList<>());
coffeeMap.get("스타벅스").add(3500);
coffeeMap.put("빽다방", new ArrayList<>());
coffeeMap.get("빽다방").add(2100);
Map<String, List<Integer>> coffeeMap2 = new HashMap<>();
coffeeMap2.put("메가커피", new ArrayList<>());
coffeeMap2.get("메가커피").add(3000);
coffeeMap2.put("스타벅스", new ArrayList<>());
coffeeMap2.get("스타벅스").add(4500);
coffeeMap.forEach((k, v) -> {
coffeeMap2.merge(k, v, (price1, price2) -> {
System.out.println("price1 = " + price1);
System.out.println("price2 = " + price2);
price1.addAll(price2);
return price1;
});
});
System.out.println("coffeeMap2 = " + coffeeMap2);
}
// 결과
price1 = [3000]
price2 = [2000]
price1 = [4500]
price2 = [3500]
coffeeMap2 = {빽다방=[2100], 메가커피=[3000, 2000], 스타벅스=[4500, 3500]} |
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
class CollectionApiTest {
@DisplayName("computeIfAbsent 가 없을 때")
@Test
void mapTest1() {
//given
Map<String, List<String>> friendsToMovies = new HashMap<>();
String friend = "Tom";
//when
List<String> movies = friendsToMovies.get(friend);
if (movies == null) {
movies = new ArrayList<>();
friendsToMovies.put(friend, movies);
}
movies.add("Star Wars");
//then
Assertions.assertThat(friendsToMovies.get("Tom")).contains("Star Wars");
}
@DisplayName("computeIfAbsent 사용 시")
@Test
void mapTest2() {
// given
Map<String, List<String>> friendsToMovies = new HashMap<>();
String friend = "Tom";
//when
friendsToMovies.computeIfAbsent(friend, k -> new ArrayList<>()).add("Star Wars");
//then
Assertions.assertThat(friendsToMovies.get("Tom")).contains("Star Wars");
}
@DisplayName("computeIfPresent 가 없을 때")
@Test
void mapTest3() {
//given
Map<String, List<String>> friendsToMovies = new HashMap<>();
String friend = "Tom";
friendsToMovies.put(friend, new ArrayList<>());
//when
List<String> movies = friendsToMovies.get(friend);
if (movies != null) {
movies.add("Star Wars");
}
//then
Assertions.assertThat(friendsToMovies.get("Tom")).contains("Star Wars");
}
@DisplayName("computeIfPresent 사용 시")
@Test
void mapTest4() {
//given
Map<String, List<String>> friendsToMovies = new HashMap<>();
String friend = "Tom";
friendsToMovies.put(friend, new ArrayList<>());
//when
friendsToMovies.computeIfPresent(friend, (k, v) -> {
v.add("Star Wars");
return v;
});
//then
Assertions.assertThat(friendsToMovies.get("Tom")).contains("Star Wars");
}
@DisplayName("computeIfPresent 사용 시 - null")
@Test
void mapTest5() {
//given
Map<String, List<String>> friendsToMovies = new HashMap<>();
String friend = "Tom";
//when
friendsToMovies.computeIfPresent(friend, (k, v) -> {
v.add("Star Wars");
return v;
});
//then
Assertions.assertThat(friendsToMovies.get("Tom")).isNull();
}
@DisplayName("compute 가 없을 때")
@Test
void mapTest6() {
//given
Map<String, List<String>> friendsToMovies = new HashMap<>();
String friend = "Tom";
friendsToMovies.put(friend, new ArrayList<>());
//when
List<String> movies = friendsToMovies.get(friend);
movies.add("Star Wars");
//then
Assertions.assertThat(friendsToMovies.get("Tom")).contains("Star Wars");
}
@DisplayName("compute 사용시")
@Test
void mapTest7() {
//given
Map<String, List<String>> friendsToMovies = new HashMap<>();
String friend = "Tom";
friendsToMovies.put(friend, new ArrayList<>());
//when
friendsToMovies.compute(friend, (k, v) -> {
v.add("Star Wars");
return v;
});
//then
Assertions.assertThat(friendsToMovies.get("Tom")).contains("Star Wars");
}
} |
marp: true
|
스터디 날짜
2023.07.21 금 9:30-10:30
내용
챕터7. 병렬 데이터 처리와 성능
챕터8. 컬렉션 API 개선
공유
최승위
이성온
정민교
The text was updated successfully, but these errors were encountered: