3일차_자바_람다식_스트림

nakyeonko3·2024년 2월 21일
0

자바 람다식 스트림


  • 자바의 람다식은 왜 등장했을까?
    • 람다식과 익명 클래스는 어떤 관계가 있을까? - 람다식의 문법은 어떻게 될까?

      익명 클래스 / 람다 / 함수형 프로그래밍 / @FunctionalInterface / 스트림 API / 메소드 레퍼런스

람다식

  • 하나의 함수를 식으로 표현한것
  • 메소드의 이름이 필요 없기 때문에 익명함수 중에 하나라고 할 수 있다.
interface Adder {
    int add(int a, int b);
}

public class PracticeLambda {

    public static void main(String[] args) {

        System.out.println(new PracticeLambda() {
            public Integer add(Integer a, Integer b) {
                return a + b;
            }
        }.add(1, 2));

        Adder adder = (a, b) -> a + b;
        System.out.println(adder.add(1, 2));

    }
}

지난 번에도 과제에서도 스트림이랑 람다식을 썼었다.

@RestController()
@RequestMapping("/api/v1")
public class CalculatorController {

    @PostMapping("/sum")
    public Integer sum(@RequestBody NumbersSumRequest request){
        return request.getNumbers().stream().reduce((a,b)->a+b).get();
    }
}

람다식을 왜 사용하는가?

class User {
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}
interface Condition {
    boolean test(User user);
}
public class Main {
    public static void main(String[] args) {
        List<User> userList = new ArrayList<>();
        userList.add(new User("Alice", 30));
        userList.add(new User("Bob", 25));
        userList.add(new User("Charlie", 35));
        userList.add(new User("David", 40));


        Condition condition = new Condition() {
            @Override
            public boolean test(User user) {
                return user.getName().startsWith("A") && user.getAge() >= 30;
            }
        };

        searchAndPrint(userList, condition);
    }

    public static void searchAndPrint(List<User> userList, Condition condition) {
        for (User user : userList) {
            if (condition.test(user)) {
                System.out.println("Name: " + user.getName() + ", Age: " + user.getAge());
            }
        }
    }
}

문제점:

  • 새로운조건 추가가 아렵다.
  • 해당 searchAndPrint는 유저가 아닌가 맞나 비교 역할만 할 수 있다.
  • 다른 조건 추가가 어렵다
  • 뒤에 작성할 람다 표현식에 비해 가독성이 낮다.

개선된 코드

interface UserCondition {
    boolean test(User user);
}
public class Main {
    public static void main(String[] args) {
        List<User> userList = new ArrayList<>();
        userList.add(new User("Alice", 30));
        userList.add(new User("Bob", 25));
        userList.add(new User("Charlie", 35));
        userList.add(new User("David", 40));

        Predicate<User> condition = user -> user.getName().startsWith("A") && user.getAge() >= 30;

        searchAndPrint(userList, condition);
    }

    public static void searchAndPrint(List<User> userList, Predicate<User> condition) {
        userList.stream()
                .filter(condition)
                .forEach(user -> System.out.println("Name: " + user.getName() + ", Age: " + user.getAge()));
    }
}

익명 클래스를 만들어서 쓰는 방식에 비해 코드가 간결해졌다.

        Condition condition = new Condition() {
            @Override
            public boolean test(User user) {
                return user.getName().startsWith("A") && user.getAge() >= 30;
            }
        };
        Predicate<User> condition = user -> user.getName().startsWith("A") && user.getAge() >= 30;

람다식 이용해서 과일 최대값, 합계 구하기


class Fruit {
    static Integer couter = 0;
    private final int id;
    private final String name;
    private final int price;

    public Fruit(String name, int price) {
        this.id = ++couter;
        this.name = name;
        this.price = price;
    }


    public Integer getId() {
        return id;
    }

    public int getPrice() {
        return price;
    }

    public String getName() {
        return name;
    }
}

public class Main {
    public static void main(String[] args) {

        List<Fruit> fruits = Arrays.asList(new Fruit("사과", 1_000), new Fruit("사과", 1_200), new Fruit("사과", 1_200), new Fruit("사과", 1_500), new Fruit("바나나", 3_000), new Fruit("바나나", 3_200), new Fruit("바나나", 3_200), new Fruit("바나나", 2_500), new Fruit("수박", 10_900));

        // 사과와 수박 중에서 2000원 보다 비싼 것만 출력
        System.out.print("사과와 수박 중에서 2000원 보다 비싼 것들: {");
        System.out.print(new Main().filterFruits(fruits, fruit -> Arrays.asList("사과", "수박")
                        .contains(fruit.getName()) && fruit.getPrice() > 2_000)
                .stream()
                .map(fruit -> fruit.getId() + fruit.getName())
                .collect(Collectors.joining(", ")));
        System.out.println("}");

        // 수박과 바나나 합계 출력
        int sum = fruits.stream()
                .filter(fruit -> Arrays.asList("바나나", "수박")
                        .contains(fruit.getName()))
                .mapToInt(Fruit::getPrice)
                .sum();
        System.out.println("합계:" + sum);

//         수박과 바나나 중에서 가장 비싼 과일 출력
        Optional<Fruit> maxFruit = fruits.stream()
                .filter(fruit -> Arrays.asList("바나나", "수박")
                        .contains(fruit.getName()))
                .max(Comparator.comparingInt(Fruit::getPrice));

        maxFruit.ifPresent(fruit -> System.out.println("가장 비싼 과일: " + fruit.getName()));

    }

    private List<Fruit> filterFruits(List<Fruit> fruits, Predicate<Fruit> fruitFilter) {
        return fruits.stream()
                .filter(fruitFilter)
                .collect(Collectors.toList());
    }
}

Spring과 MySql 연결


DDL

데이터 정의어

DML

데이터 조작어

주의: 조건을 붙이지 않았기 때문에 모든 fruit의 가격이 1500으로 변경된다.

update fruit set price = 1500; 
update fruit set price = 1500 where name = "사과"; 

MySql 연결 설정

intellj 메소드 검색 단축키

ctrl + shift + n

트랜잭션

수동 트랜잭션 예제
실행된 ddl 롤백시키는 예제

create table user
(
    id   bigint auto_increment,
    name varchar(25),
    age  int,
    primary key (id)
);

select *  from user;
start transaction;
insert into user(age, name)
values (10, 'nakyenko');
select *
from user;
rollback;
select *  from user;

의문점과 질문

Q: log 메서드가 뭐지?
로깅? 할 때 쓰는 거라는데 정확히 뭔지는 모른다.

Q: 도메인 클래스랑 DTO 차이가 뭐지?
막상 코드를 작성해보니까 별차이가 없는거 같은데 내가 뭘 잘 못한건가

Q: 어떻게 하면 코드를 더 잘 정리할 수 있을까
소스코드를 도메인명+명사 이런식으로 정리하니까 편하다

Q: application.yml 파일을 암호화 할 필요가 있다.
저 yaml 파일에 내 mysql 주소랑 비밀번호까지 다 들어나고 있다.
일단은 github에 올라간 yaml 파일은 삭제했다.

참고


profile
웹개발자를 지망하고 있는 대학생, 진순파

0개의 댓글