BEYOND SW 캠프 21기 7회차 회고

컨테이너·2025년 11월 9일
post-thumbnail

📝7회차 회고록ㅣBEYOND SW캠프


🖥️ 7회차 학습 (25.11.03 ~ 25.11.07) 기록

지난주에 이어 JAVA 후반부의 내용을 배웠다. 중요한 내용들인 만큼 하루하루 소화해 내는데 바빴던 한 주였던 것 같다. 배운 내용은 아래와 같다.

chap14. 컬렉션(>클릭<)
chap15. Enum
chap16. 람다(클릭)
chap17. 스트림(클릭)
chap18. 스레드(클릭)
chap19.Juni(클릭)
자료구조 & 알고리즘(클릭)

내용 하나하나 하루만에 다 습득하기란 물론 불가능한 내용들이지만, 이번 회고도 새롭게 배우고 기억해야 하는 내용들 위주로 작성해 보겠다.

👍 KEEP


  • 자바의 자료구조 컬렉션 List,Set,Map 에 대한 이해와 사용 방법 → 계속 익혀나가자
  • 람다 연습문제 해결 방법이 이해가 안되고 헷갈렸지만 도움으로 람다에 대한 이해와 문제 풀이 할 수 있었던 것
  • 지난 주 PCCP 리뷰를 통해 도움 받고 이해했던 것 → 모르는 것 질문
  • 풀지 못할 뻔 했던 과제 포기 안하고 끝까지 풀었다.
  • 쿠팡에서 완제품 밥과 소스 닭가슴살을 도시락으로 싸와보았는데 생각보다 괜찮았다.

✏️ NEW


과제<람다>

람다문제:로또람다 문제: 로또

로또 번호 생성하는 람다 식을 세우시오

람다에 대한 이해도가 부족하여 이 문제를 풀 때 동기분의 도움을 받아 풀었다. 이를 통해 어느 정도 람다에 대한 이해가 생겼지만, 그 전까지 감을 잘 못잡았다.

Set() 을 사용하고, 로또 번호 생성을 위해 random()을 사용해야겠다는 생각만 가지고 문제를 풀었지만, 아래와 같이 한 줄만 쓰고 아무것도 못했다.

Function<Set<Integer>> set = () -> (int)((Math.random()*45)+6);

람다 Comsumer, Supplier, Function 중 하나를 써야겠다는 생각은 들었지만 내부 람다 사용과 로직에 대해 아무런 아이디어도 떠오르지 않고, 수업자료들을 참고해보아도 어떤 식으로 풀어야 할지 감이 오지 않았다.

그렇게 동기분에게 어떤 식으로 풀어야 할지 질문헀는데, 동기분이 이해가 아예 안될 때는 답을 확인하고 시작하는 것도 이해에 도움이 될 때가 많다며 답을 부여 준 것이 많은 도움이 되었다.

내가 했던 실수는 아래와 같다.

  • 람다와 로또 생성 로직을 한 줄안에 단번에 사용하려 했다. 천천히 하나씩 나누어 생각하여 람다 타입을 정하고, 어떤 자료형을 반환 받을 지, 어떤 함수를 써서 자료형에 어떻게 담을지 차근히 생각했어야 했다. 하지만 단번에 급하게 하려다 보니 마음이 급했다.

정답정답

Supplier<Set<Integer>> lotto = () -> {
    Random random = new Random();
    Set<Integer> lottoSet = new HashSet<>();
    while (lottoSet.size() < 6) {
        lottoSet.add(random.nextInt(100));
    }
    System.out.println(Arrays.toString(lottoSet.toArray()));
    return  lottoSet;
};
lotto.get();

Supplier<Set<Integer>> lotto =
해당 로또 문제는 입력 X 반환 X 출력 O 이므로, Comsumer 나 Supplier를 사용하면 된다. 로또는 중복제외&정수값이니 반환 자료형은 Set<Integer> 이다.

과제<스트림>

스트림문제1스트림 문제 1번

이 문제는 User 클래스에서 나이가 20세 이상인 객체를 이름만 리스트로 출력하는 문제이다.

내가 작성한 코드는 아래와 같다. 하지만 계속해서 경고가 떠서 한 동안 막혀있었다.

Stream<User> streamUsers = users.stream();
	streamUsers
        .filter(user -> user.getAge() >= 20)
        .map(User::getName)   
        .collect(Collectors.toList()); 
        
System.out.println(names);

내가 했던 실수는 Stream<User> 타입으로 .collect() 를 통해 리스트로 받아오려고 했던 것이다. 타입에러의 일종인 것이다.

정답정답

List<String> names = users.stream()             // Stream 생성
        .filter(user -> user.getAge() >= 20)    // 조건: 나이 20 이상
        .map(User::getName)                     // 이름만 추출
        .collect(Collectors.toList());          // List로 수집
        
System.out.println(names);

.collect() 로 모아서 리스트로 만들기 위해서는 names를 List 타입으로 선언하여, .stream()으로 스트림으로 변경해야 했다. 이를 통해 문제를 해결했다.

배운것배운 것

  • stream()은 1회용이라 생성한 스트림을 streamUsers 변수로 따로 저장할 필요 없이 바로 사용하면 된다. 선언 후 곧바로 이어쓰는 것을 의미한다.
  • .collect() 를 쓰려면 List<T> 타입으로 받아와야 한다.

스트림문제2스트림 문제 2번

이번 문제는 null이 아닌 문자열 중 "java"를 포함하는 텍스트만 소문자로 출력하고, Objects::nonNull를 이용해서 null 체크하는 문제이다.

내가 작성한 코드는 아래와 같다.

List<String> result = texts.stream() 
  		.map(Objects::nonNull) 
  		.filter(str->str.toString().contains("java")) 
  		.map(text -> text.toString().toLowerCase()) 
  		.forEach(System.out::println);

이렇게 작성했는데, .forEach()에서 호환되지 않는 타입이라는 컴파일 오류가 계속 떴다. 위 코드에 어떤 오류가 있는지 하나씩 알아가 보자.

  • .map(Objects::nonNull)
    map은 변환용 메서드이다. 스트림내 요소들에 대해 함수가 적용된 결과의 새로운 요소로 매핑해준다. 위 상황에서는 .map이 아니라, filter() 가 적합하다. 게다가 null 이 들어와 boolean 오류가 생길 것이다.

  • .filter(str->str.toString().contains("java"));
    이 또한 null 때문에 널포인트에러가 뜰 것이다.

  • .map(text -> text.toString().toLowerCase())
    이 전에 null 제거가 되지 않았기 때문에 연쇄적으로 nullPointerError가 발생할 것이다.

  • .forEach(System.out::println);
    forEach() 는 void를 반환하기에 List<String> 타입과 알맞지 않다.

정답정답

List<String> result = texts.stream()
        .filter(Objects::nonNull)                // null 제거
        .filter(str -> str.toLowerCase().contains("java")) // "java" 포함 여부
        .map(String::toLowerCase)                // 소문자로 변환
        .collect(Collectors.toList());           // 리스트로 수집

result.forEach(System.out::println);             // 출력
  • filter(Objects::nonNull)
    → null만 제거: map이 아닌 필터로 수행한다.
  • filter(str -> str.toLowerCase().contains("java"))
    대소문자 구분 없이 "java" 포함된 문자열만 필터링해줌
  • map(String::toLowerCase)
    모두 소문자로 변환해준다. toLowerCaseString 메소드이므로 메소드 레퍼렌스::로 간략하게 작성해보았다.
  • collect(Collectors.toList())
    collect() 로 결과를 리스트로 모아준다. List<String> 타입으로 가져왔으니, 동일한 타입으로 반환해주자.

출력결과출력 결과

i love java
java is fun

배운것배운것

  • null 제거는 filter(Objects::nonNull) : map 아니다. map은 스트림 각 요소 어케 바꿀지 정해줌
  • map은 변환용, filter는 조건검사용임
  • forEach는 결과 출력용이며, collect는 리스트 반환이라 같이 못쓴다.

스트림문제3스트림문제3번

문제: 길이가 3 이상인 문자열만 골라 쉼표로 연결하여 출력하세요.

List<String> words = List.of("hi", "hello", "to", "world", "java"); 
  
Stream<String> wordsStream = words.stream()
  		.filter(word -> word.length() >= 3) 
  		.collect(Collectors.joining(",")); 

// 출력값 // hello, world, java

안풀렸다. 조금씩 바꿀 때마다 다른 오류가 발생하고 계속해서 생기는 오류를 잡기가 안되어 오류를 잡는데 정말 오래 걸렸다. 길이가 3이상인 문자열을 연결해주면 되는것 아닌가 해서, .filter()collect()joinging() 만 적절히 사용하면 금방 끝날 줄 알았다.

이번에 잘못한 것도 collect() 사용 시 반환 타입에 있어서 발생했다.
collect(Collectors.joining(","))Stream<String>이 아니라 String을 반환 한다는 것이다.

그래서 wordsStream의 타입을 Stream<String>이 아니라 String으로 받아한다.

정답정답

List<String> words = List.of("hi", "hello", "to", "world", "java");

String result = words.stream()                 // String 타입을 스트림 화
        .filter(word -> word.length() >= 3)    // 길이가 3 이상
        .collect(Collectors.joining(", "));    // 연결

System.out.println(result);
hello, world, java

배운점배운점

  • Collectors.joining(delimiter) → 스트림의 문자열 요소를 구분자 기준으로 하나의 문자열로 합침. 결국 반환하는 것이 String 타입이기 때문에, 얘를 받아줄 얘도 String 타입이어야 한다.
  • .collect(Collectors.joining(",")) 결과 타입은 String → 받아줄 타입을 Stirng result로 스트링 타입으로 객체를 생성해서 스트림화시키고, 조건을 맞춘 후 collect()에 담아 다시 String으로 반환한다.

💡 PROBLEM


  • 람다와 스트림에 대한 이해도가 떨어져서 이후 수업과 과제에서 많이 헤맸다.
  • ArrayList 와 LinkedList로 구현한 Stack 흐름은 이해했으나 코드 이해가 안됐다
  • Junit 을 직접 해보라고 하면 헤멜듯 하다. 많이 사용해 보고 직접 많이 작성해봐야 감이 올듯하다.
  • 힙, 트리 그래프 등 중요한 자료구조 수업이 있었는데 요근래 집중하기 가장 힘들었다. 자료구조를 예전에 한번씩봤다고 소홀이 여겼던 점이 있다.

🪛 TRY


  • 100% 이해하고 넘어가는 것 보다 앞서 다가올 스프링 & 파이널 프로젝트 대비 & 실질적 취업준비 중요도를 잘 따져서 시간을 사용해보자.
profile
백엔드

0개의 댓글