[250310 TIL] 스트림으로 리스트 중복 개수 세기
오늘 가장 어려웠던 코드
// 중복 메뉴 합산 처리
cartItems.stream()// 스트림으로 변환
.collect(Collectors.groupingBy(item -> item, Collectors.counting())) // 개수 미리 계산
.entrySet().stream()
.sorted(Map.Entry.comparingByKey(Comparator.comparing(MenuItem::getName))) // 정렬 추가
.forEach(entry -> {
MenuItem item = entry.getKey();
long count = entry.getValue();
double totalItemPrice = item.getPrice() * count;
System.out.printf("%d. %s | %d개 | W %.2f%n", index.getAndIncrement(), item.getName(), count, totalItemPrice);
});
코드 분해해서 이해하기
| 코드 | 설명 |
| cartItems.stream() | 장바구니 목록을 스트림으로변환 |
| .collect(Collectors.groupingBy( item -> item, Collectors.counting())) |
cartItems에 있는 동일한 MenuItem을 그룹화하고 개수를 계산해서 Map에 저장 groupingBy(item -> item) : 동일한 MenuItem을 그룹화 Collectors.counting() : 그룹별 개수를 세서 Long값으로 저장 |
| .entrySet().stream() | Map을 스트림으로 변환 |
| .sorted(Map.Entry.comparingByKey (Comparator.comparing (MenuItem::getName))) |
메뉴 이름 기준으로 정렬 MenuItem객체의 getName()값을 기준으로 오름차순 정렬 Map.Entry.comparingByKey() : 키(MenuItem)를 기준으로 정렬 Comparator.comparing(MenuItem::getName) : MenuItem의 getName()을 기준으로 비교 |
| .forEach(entry -> { MenuItem item = entry.getKey(); long count = entry.getValue(); double totalItemPrice = item.getPrice() * count; System.out.printf("%d. %s | %d개 | W %.2f%n", index.getAndIncrement(), item.getName(), count, totalItemPrice); }); |
최종 출력 entry.getKey() : MenuItem 객체 가져오기 entry.getValue() : 해당 MenuItem이 몇 개 있는지 가져오기 totalItemPrice = item.getPrice() * count; : 개수에 맞춰 총 가격 계산 index.getAndIncrement : 출력할 때 번호 자동 증가 |
이거 한다고 머리 빠지는 줄 알았다....
코드의 흐름
1. cartItems.stream()
→ 장바구니 목록을 스트림으로 변환
2.. collect(Collectors.groupingBy(item -> item, Collectors.counting()))
→ 같은 메뉴를 그룹화하고 개수를 센다 (Map<MenuItem, Long>)
3.. entrySet(). stream()
→ Map을 스트림으로 변환하여 다룰 수 있게 한다
4.. sorted(Map.Entry.comparingByKey(Comparator.comparing(MenuItem::getName)))
→ 메뉴 이름을 기준으로 정렬한다
5.. forEach(entry -> {... })
→ 출력 형식대로 한 줄씩 출력한다
오늘 처음 써본 자바 기능
AtomicInteger : int , Integer는 멀티스레드 환경에서 동기화 없이 값을 변경하면 예상치 못한 오류가 발생할 수 있지만 Atomic Integer는 내부적으로 CAS(Compare-And-Swap) 알고리즘을 사용하여 동기화 없이 안전하게 값을 변경
사용이유 : forEach문에서
int index = 1;
cartItems.stream()
.forEach(item -> {
System.out.printf("%d. %s%n", index++, item.getName());
});
이런 식으로 사용하려고 하니 오류가 발생해서
AtomicInteger index = new AtomicInteger(1);
cartItems.stream()
.forEach(item -> {
System.out.printf("%d. %s%n", index.getAndIncrement(), item.getName());
});
AtomicInteger를 사용해서 값을 안전하게 증가시키면서 출력 가능
AtomicInteger 주요 메서드
| 메서드 | 설명 |
| get() | 현재 값을 가져온다. |
| set(int newValue) | 값을 새로운 값으로 설정한다. |
| incrementAndGet() | 현재 값을 1 증가시키고, 증가된 값을 반환한다. |
| getAndIncrement() | 현재 값을 더한 후 새로운 값을 반환한다. |
| addAndGet(int a) | 주어진값을 더한 후 새로운 값을 반환한다. |
| getAndAdd(int a) | 현재 값을 반환하고, 이후 주어진 값을 더한다. |
| compareAndSet(int expect,int update) | 현재 값이 기대값(expect)과 같다면 업데이트(update)한다. |
키오스크 LV.6 코드
https://github.com/sukh115/Kiosk/tree/main/src/kioskLv6
Kiosk/src/kioskLv6 at main · sukh115/Kiosk
Contribute to sukh115/Kiosk development by creating an account on GitHub.
github.com