람다식과 익명 클래스는 어떤 관계가 있을까? - 람다식의 문법은 어떻게 될까?
익명 클래스 / 람다 / 함수형 프로그래밍 / @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());
}
}
}
}
문제점:
개선된 코드
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());
}
}
데이터 정의어
데이터 조작어
주의: 조건을 붙이지 않았기 때문에 모든 fruit의 가격이 1500으로 변경된다.
update fruit set price = 1500;
update fruit set price = 1500 where name = "사과";
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 파일은 삭제했다.