TIL 10 [ Java(람다식, 스트림, 쓰레드) + 계산기 과제 1단계 ]

2025. 2. 28. 21:58·[내일배움캠프-Sparta]/Spring 6기
반응형

1. 오늘 학습 키워드 : Java 프로그래밍 ( 람다식, 스트림 ,쓰레드 ) , 계산기 과제 1단계

2. TMI
오늘부로 이제 매일아침 부터 sql, 알고리즘 문제를 한두문제씩 풀고 제출해야한다....

해야할게 하나 늘었지만, 코딩 실력을 올리는데 있어서 매우 중요한 시간이 될것같다.

 

3. 학습내용

[3-5 람다식]

익명 클래스 - 이름이 없는 클래스,  별도의 클래스 파일을 만들지 않고 코드 내에서 1회성으로 정의해서 사용

☞ 인터페이스, 클래스(일반, 추상) 의 구현과 상속을 활용해 구현 가능하다.        → 람다에서는 인터페이스를 사용한 익명 클래스가 활용됨.

익명 클래스 ex

람다(Lambda) - 람다 는 익명클래스를 더 간결하게 표현하는 문법

함수형 인터페이스를 통해서 구현하는 것을 권장 ( @FuntionalInterface 어노테이션 선언 ! ! )

→  하나의 추상 메소드만 가져야하기 때문

→  하지만, 하나의 추상 메소드를 가진 일반 인터페이스를 통해 사용가능함.

★ 함수형 인터페이스에 추상 메소드가 하나뿐 이기 때문에 컴파일러는 람다표현식 그 해당 메소드라고 추론 가능

 

람다 사용시 주의사항

  • 함수형 인터페이스는 단 하나의 추상 메소드만 가지도록 강제하는 어노테이션
  • 람다식에서 함수형 인터페이스 활용 가능
  • 인터페이스에 2개 이상의 추상 메소드가 존재하면, 컴파일러가 어떤 메소드를 구현하는지 모호해짐.
  • 오버로딩 기능을 통해 동일 명의 메서드를 여러 형태로 정의한다면, 람다 표현식이 어떤 메소드를 구현하는 것이 명확하지 않아 모호해짐

★ 오버로딩 -  같은 클래스나 인터페이스 내 동일한 메소드 이름을 사용해 선언하는 기능.

→ 메소드명은 동일하며, 매개변수의 타입이나 개수, 순서는 다르게 선언  ( 생성자에서 주로 쓰임 )

public class Person {

	private String name;
	private int age;
    
    // 생성자 오버로딩
    public Person() {}
    
    public Person(int age) {
    	this.age = age;
    }
    
    public Person(String name, int age) {
    	this.name = name;
    	this.age = age;
    }
    
    public void run() {
    	System.out.println("달린다.");
    }
}

★ 오버라이딩 - 부모 클래스에 정의된 메소드를 자식 클래스에서 재정의 하는 것  ( 주로 상속관계에서 다룸 )

public class Hero extends Person {

	// 메소드 오버라이딩 ( 부모 메소드를 재정의 함 )
	public void run() {
    	System.out.println("히어로는 멋지게 달린다");
    }
}

 

람다식 다양한 매개변수 전달법

[3-6 스트림]

스트림 - 데이터를 효율적으로 처리할수 있는 흐름 ( 스트림은 컬렉션과 함께 자주 활용됨 )

데이터 준비 → 중간 연산 → 최종 연산 순으로 처리

실무에서 자주 쓰이는 map(), filter()

 

ArrayList를 List로 받는 이유

다형성을 활용해 List 인터페이스로 ArrayList 구현체를 받으면, 나중에 다른 구현체 ( LinkedList, Vector )로 변경 할때 코드 수정을 최소화 할 수 있다. → 실무에서 리스트로 선언시, List타입으로 받는것을 권장

 

ArrayList<> 다음 list.of()함수는 선언과 동시에 값을 저장한다는 개념으로 보면 편하다.

 

데이터 준비

stream() - 데이터를 스트림으로 변환해 연산흐름을 만들 준비함.

중간 연산

map() - 각 요소를 주어진 함수에 적용해 변환

filter() - 각 요소를 주어진 조건에 따라 추출해냄

최종 연산

collect() - 결과를 원하는 형태(List,  set)으로 수집함.

 

*실습문제*

 💬 Q1. filter를 람다식으로 활용해 보세요.

 💡요구사항

  1. 익명 클래스 활용
  2. 람다식 만들기
  3. 직접 람다식 대입

Q1 실습문제 풀이 ( 스트림 )

Predicate 인터페이스는 한 개의 제네릭 타입을 사용하며,

내부에는 한 개의 추상 메서드, 세 개의 디폴트 메서드, 한 개의 정적 메서드가 존재합니다

[3-7 쓰레드]

쓰레드 - 프로그램 내에서 독립적으로 실행되는 하나의 작업단위 

 

싱글 쓰레드 (1명의 일꾼이 작업 처리) -  일꾼이 1명이기 때문에 여러개의 작업이 있으면 순차적으로 처리

main() 메소드는 프로그램과 시작 동시에 생성되는 하나의 쓰레드 임.

 

멀티 쓰레드 (작업을 처리할수 있는 여러명의 일꾼) - 여러 작업을 병렬(동시) 처리할 수 있다. ( Thread 클래스를 상속받아 쓰레드를 구현 할수 있음. )

Thread.run() 메소드를 오버라이딩 해서 쓰레드가 수행할 작업을 정의함.

Start() 메소드를 호출하면 새로운 쓰레드가 생성되고, run()의 작업 내용이 실행된다.

쓰레드 실습코드

총 3개의 쓰레드 ( main, thread0, thread1 ) 병렬로 실행.

★ 쓰레드를 실행시킬때 꼭 start()로 실행하기

☞ start()는 새로운 쓰레드에서 run()을 실행

☞ run()을 직접 호출하면, 현재 쓰레드에서 실행됨.

 

join() [ 특정 쓰레드가 끝날때 가지 기다리기 ] - main() 쓰레드가 다른 쓰레드가 종료될때 까지 기다리게 하는 메서드

 

Runnable 인터페이스 활용 - Runnable 인터페이스를 활용해 쓰레드를 구현하는 것을 권장함.

  1. 유지 보수성과 재사용성 향상
  2. 확장 가능성

■  계산기 과제 1단계 ■

클래스 없이 기본적인 연산을 수행할 수 있는 계산기 만들기
package com.example.calculator;

import java.util.Scanner;

public class Calculator {
    public static void main(String[] args) {
        // 1단계 클래스 없이 기본적인 연산을 수행할 수 있는 계산기 만들기
        Scanner sc = new Scanner(System.in);
        while (true){
            System.out.print("첫번째 정수를 입력하세요: ");
            int num1 = sc.nextInt();
            // 양의 정수(0포함) 만 입력받아야 하는 조건
            if (num1 < 0) {
                System.out.println("음수는 입력할수 없습니다.");
                continue;
            }
            
            System.out.print("두번째 정수를 입력하세요: ");
            int num2 = sc.nextInt();
            if (num2 < 0) {
                System.out.println("음수는 입력할수 없습니다.");
                continue;
            }

            System.out.print("사칙연산(+, -, x, /) 기호를 입력하세요: ");
            char operator = sc.next().charAt(0); // 문자열에서 첫 번째 문자만 추출

            int result = 0;

            switch (operator) {
                case '+':
                    result = num1 + num2;
                    break;
                case '-':
                    result = num1 - num2;
                    break;
                case '*':
                    result = num1 * num2;
                    break;
                case '/':
                    if (num2 == 0) {
                        System.out.println("나눗셈 연산에서 분모(두번째 정수)에 0이 입력될 수 없습니다.");
                        break;
                    } else {
                        result = num1 / num2;
                        break;
                    }
                default:
                    System.out.println("부호를 잘못 입력하였습니다.");
            }
            System.out.println("결과 = " + result);

            sc.nextLine(); // 버퍼 비우기 (중요) 엔터값이 남아있어서 초기화 필요함!!

            System.out.print("더 계산하시겠습니까? (exit 입력 시 종료): ");
            String answer = sc.nextLine();

            if (answer.equals("exit")) {
                System.out.println("계산기 시스템을 종료합니다.");
                break;
            }
        }

    }
}

 

[트러블 슈팅]

  • 배경 : 사용자가 입력한 후 바로 다음 입력창이 넘어가는 입력 누락 현상을 발견했다. 이는 Scanner를 사용할 때, 버퍼(buffer) 문제가 발생했기 때문으로 추측된다.
  • 발단 :처음에는 nextInt()로 정수를 입력받고, nextLine()을 사용하여 추가 입력을 받으려 했지만,
    예상과 달리 nextLine()이 입력을 받지 않고 건너뛰는 현상이 발생했다.
    이 때문에 "더 계산하시겠습니까?"라는 질문이 사용자의 입력 없이 바로 넘어갔다.
  • 전개 : nextInt()는 정수만 읽고 개행 문자(\n)는 버퍼에 남겨둔다.  이후 nextLine()이 실행되면 남아 있는 \n을 읽어들여, 사용자가 입력한 것처럼 처리한다.  ( 개행이 버퍼에 남아있기 때문 )
  • 위기 : 처음에는 nextLine()을 바로 호출하는 것이 문제라고 생각해 입력 방식을 변경해보았지만, 문제는 여전히 해결되지 않았다. 이를 해결하기 위해 사용자의 입력 흐름을 고려한 근본적인 해결책이 필요했다.
  • 절정 : 문제를 해결하기 위해 버퍼를 비우는 작업을 추가했다.
    즉, nextInt()로 숫자를 입력받은 후, nextLine()을 한 번 실행하여 남아 있는 개행 문자(\n)를 제거하는 방법을 적용했다
  • 결말 : 이제 프로그램이 정상적으로 동작하며, 사용자가 원하는 입력을 정상적으로 받을 수 있게 되었다.
    앞으로도 입력을 받을 때, Scanner의 버퍼 문제를 고려하여 nextLine()을 적절히 활용하는 습관을 들이면,
    유사한 문제 발생을 방지할 수 있다. ( 항상 스캐너 입력 받을때 nextLine() 을 활용해 버퍼 지우는 습관 가지기 )

버퍼는 입력 데이터를 임시적으로 저장하는 공간이라고 생각하면 좋다. 

→ 입력이 끝난후 남아있는 불필요한 데이터를 처리하지 안흥면 예상치 못한 동작을 할 수 있다. 이를 방지하려면 버퍼에 남은 개행 문자를 처리하기 위해 nextLine()을 한 번 호출해서 버퍼를 비워줘야 한다.

 

4. 내일 학습 할 것: 주말동안 자바,git 복습

반응형

'[내일배움캠프-Sparta] > Spring 6기' 카테고리의 다른 글

TIL 12 [계산기 과제 3단계(enum, 제네릭, 람다, 스트림)]  (0) 2025.03.05
TIL 11 [Java(접근제어자, 클래스란?, 객체지향?) + 계산기 과제 2단계 ]  (0) 2025.03.04
TIL 9 [ Java(예외처리, Optional, 제네릭, 컬렉션) ]  (0) 2025.02.27
TIL 8 [ Java(final, static, 인터페이스, 객체지향) ]  (0) 2025.02.26
TIL 7 [ Java(조건/반복문, 배열 , 메소드) ]  (0) 2025.02.25
'[내일배움캠프-Sparta]/Spring 6기' 카테고리의 다른 글
  • TIL 12 [계산기 과제 3단계(enum, 제네릭, 람다, 스트림)]
  • TIL 11 [Java(접근제어자, 클래스란?, 객체지향?) + 계산기 과제 2단계 ]
  • TIL 9 [ Java(예외처리, Optional, 제네릭, 컬렉션) ]
  • TIL 8 [ Java(final, static, 인터페이스, 객체지향) ]
dimenshun
dimenshun
한 소년의 개발 일기
    반응형
  • dimenshun
    Dev Life Notes
    dimenshun
  • 전체
    오늘
    어제
    • 분류 전체보기 (268)
      • CS (23)
        • 자료구조 (0)
        • 알고리즘 (0)
        • 컴퓨터 구조 (8)
        • 네트워크 (6)
        • 운영체제 (3)
        • DB ( + SQLD ) (5)
        • SW공학 (1)
      • 프로그래밍 (3)
        • Java (0)
        • Spring (0)
        • HTML,CSS (3)
        • JavaScript (0)
      • 개발 툴 (7)
        • Git(버전관리) (1)
        • Docker (3)
        • AWS (2)
        • JSP (1)
      • 코딩테스트(Algorithm) (125)
        • 백준 (6)
        • 프로그래머스 (119)
      • [내일배움캠프-Sparta] (110)
        • Spring 6기 (106)
        • KPT 회고 (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    백엔드
    배포
    cs
    network
    Python
    웹
    SQLD
    OS
    AWS
    개발자
    코딩테스트
    docker
    네트워크
    KPT
    트랜잭션
    CPU
    컴퓨터구조
    세션
    db
    spring
    It
    메모리
    운영체제
    web
    SQL
    Til
    알고리즘
    Testcode
    내일배움캠프
    Java
  • hELLO· Designed By정상우.v4.10.3
dimenshun
TIL 10 [ Java(람다식, 스트림, 쓰레드) + 계산기 과제 1단계 ]
상단으로

티스토리툴바