[본캠프] 17일차

윤영범·2026년 4월 1일

Stream을 “제대로” 쓰는 방법

기존에는 for문으로만 리스트를 순회했지만,
Stream을 사용하면 데이터를 조회 / 필터링 / 변환하는 의도를 더 명확하게 표현할 수 있다는 것을 배웠다.

기존 방식 (for문)

double total = 0;
for (Cart cart : cartlist) {
total += cart.getPrice() * cart.getCartamount();
}

개선 (Stream 사용)

return cartlist.stream()
.mapToDouble(cart -> cart.getPrice() * cart.getCartamount())
.sum();

  • “각 Cart를 총 가격으로 변환 → 합계”라는 흐름이 명확해짐

Stream 주요 활용 패턴
filter() → 조건에 맞는 데이터 찾기
sorted() → 정렬
flatMap() → 중첩 리스트 펼치기
mapToDouble() → 값 변환
sum() → 합계 계산
removeIf() → 조건 삭제
bag.removeIf(cart -> cart.getName().equals(product.getName()));

  • Stream 기반으로 컬렉션을 더 간결하게 처리 가능
    다른사람들의 스트림예제를 참조하면서, 천천히 응용시켜보니 그래도 조금씩 감이 잡히는거 같았다
    단지 어디서 써야하는지 명확하게 생각해야할거같다
    Stream은 “반복문을 줄이는 도구”가 아니라
    데이터를 어떻게 처리할지 표현하는 방식이라는 것을 이해했다.

트러블 슈팅 과정

Stream 사용시 index 설계

Stream은 forEach로 요소를 꺼내기 때문에
기본적으로 index를 제공하지 않는다.

categories.stream()
        .forEach(category -> {
            // index 없음
        });

그래서 기존처럼 i + 1을 사용할 수 없었다.
IntStream.range()를 사용하면
index 기반으로 Stream을 만들 수 있다는 것을 알게 되었다.

IntStream.range(0, categories.size())
        .forEach(i -> {
            System.out.println((i + 1) + "." + categories.get(i).getCategory());
        });
  • IntStream.range(0, n) → 0부터 n-1까지 숫자 스트림 생성

제대로된 설계없이 절차지향적인방향

초반에 제대로된 설계없이 가는대로 코드를 짜다보니, 코드가 길어지면서 내가 어디부분을 작성해야하는지 제대로 알수가없었다 수정을하면서 할수록 머리가 아파지는구조였다

            System.out.println("4.장바구니 확인");
                System.out.println("5.주문 취소");
            }

            System.out.println("0.종료하기");
            int num = sc.nextInt();
            sc.nextLine();

            /// //////---------------------------------------------------------------------------------메인메뉴출력
        //-----------------0-------------------메뉴시작-----------------------------------------------------------------
            if (num == 0) {
                break;
            }
            List<Product> products = null; //변수 스코프 List 값은 null 포함한다
            if (num > 0 && num <= categories.size()) {

                Category catenum = categories.get(num - 1); // 인덱스 0부터시작 선택
@@ -49,87 +62,77 @@ public void start() {
                            product.getPrice(),
                            product.getInfo());
                }
            } else {
            }
            if(num == 4){//장바구니확인
                if(!c_list.isEmpty())
                {
                    System.out.println("[ 장바구니 내역 ]");
                    cartlist.showCartlist();
                    System.out.println("[ 총 주문 금액 ]");
                    System.out.println(cartlist.totalPrice());

                } else {
                    System.out.println("장바구니가 비어있습니다");
                    continue;
                }
                System.out.println("1.주문 확정 \t 2.메인으로 돌아가기");

                int total = sc.nextInt();

                if(total == 1){

                    System.out.println("주문이 완료되었습니다! 총 금액 : " + cartlist.totalPrice());
                    cartlist.updateAmount();
                    continue;
                }
            }
            if(num == 5){       //장바구니확인
                cartlist.showCartlist();
                System.out.println("취소할 상품번호 선택 \t 0.메인으로 돌아가기");
                int cartidx = sc.nextInt();
                cartlist.removeCartlist(cartidx);

CommerceSystem.java 일부
모든 출력을 다 Start() 함수에 넣어버려서 어디를 찾자니 제대로 찾을수가없는구조였다

개선

출력하는 코드를 메소드로 빼버리고 기능적인부분도 메소드로 빼버리면서 객체지향의 중요성을 다시한번느끼게되면서 설계의 중요성을 강하다 깨달았다

Enum 클래스 활용

설계구조

Enum Values라는 내부함수로 Grade 내 모든 객체를 불러와 그의 맞는 할인을 적용하려고했다![]

처음에 Enum을 사용할 때, 객체처럼 생각하고 접근하려고 했다.

Grade.showGrade();

이와 같이 Grade 내부 메서드를 바로 호출하려고 했는데,
static이 없어서 다음과 같은 오류가 발생했다.

Non-static method cannot be referenced from a static context

문제 원인

처음에는 Enum을 “객체”라고만 이해해서
메서드도 일반 클래스처럼 동작할 것이라고 생각했다.

하지만 showGrade() 메서드는 static이 아니었기 때문에
객체를 생성하지 않고는 호출할 수 없었다.

즉,

객체 없이 메서드를 호출하려고 해서 발생한 오류

였다.

해결 방법

showGrade()와 선택된 숫자의 할인값을 가져오는 discountIdx()는 특정 객체가 아니라
전체 Enum 값을 기준으로 동작하는 메서드이기 때문에
static으로 선언해야 했다.

public static void showGrade() { ... }

public static Grade discountIdx(int idx) { ... }

static은 “객체 없이도 사용할 수 있는 메서드”라는 의미이다

개선해야할점

예외처리 구조를 파악하기가힘들었다
정수를 집어넣어야하는 Scanner에 문자열을 집어넣으면 터지는거까지는 이해하겠는데
다른예외처리에 대해서 생각해본적이 거의없었는데 이번프로젝트를 계기로 공부해야될거같다

throw 예외처리의 허용

  • 메서드가 값 검증 책임을 가질때

입출력에서는 사용 X

대표적으로 for문을 돌려서 데이터를 찾고자 했을때 null값이나 idx를 잘못가져왔을경우,
이 경우의 예외처리의 대해서 제대로된 학습이 필요한거같다

0개의 댓글