[์ธํ๋ฐ/SPRING] ํ์๊ด๋ฆฌํ๋ก๊ทธ๋จ - ๋ฆฌํฌ์งํ ๋ฆฌ ํ ์คํธ ์์ฑ Optional<T>/stream().Filter/findAny()/@AfterEach
๐ฉํ์ ๊ฐ์ฒด
package hello.hellospring.domain;
public class Member {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
๐ฉํ์ ๋ฆฌํฌ์งํ ๋ฆฌ ์ธํฐํ์ด์ค
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import java.util.List;
import java.util.Optional;
public interface MemberRepository {
Member save(Member member);
Optional<Member> findById(Long id);
Optional<Member> findByName(String name);
List<Member> findAll();
}
๐ฉํ์ ๋ฆฌํฌ์งํ ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ ๊ตฌํ์ฒด
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import java.util.*;
/**
* ๋์์ฑ ๋ฌธ์ ๊ฐ ๊ณ ๋ ค๋์ด ์์ง ์์, ์ค๋ฌด์์๋ ConcurrentHashMap, AtomicLong ์ฌ์ฉ ๊ณ ๋ ค
*/
public class MemoryMemberRepository implements MemberRepository {
private static Map<Long, Member> store = new HashMap<>();
private static long sequence = 0L;
@Override
public Member save(Member member) {
member.setId(++sequence);
store.put(member.getId(), member);
return member;
}
@Override
public Optional<Member> findById(Long id) {
return Optional.ofNullable(store.get(id));
}
@Override
public List<Member> findAll() {
return new ArrayList<>(store.values());
}
@Override
public Optional<Member> findByName(String name) {
return store.values().stream()
.filter(member -> member.getName().equals(name))
.findAny();
}
public void clearStore() {
store.clear();
}
}
๐๐๋์์ฑ ๋ฌธ์ : ConcurrentHashMap, AtomicLong
๐๐Optional<T>
: null์ด ์ฌ ์ ์๋ ๊ฐ์ ๊ฐ์ธ๋ Wrapper ํด๋์ค. NPE(NullPointerException)๊ฐ ๋ฐ์ํ์ง ์๋๋ก ๋์์ค๋ค.
๐๐stream()
: ์คํธ๋ฆผ(Streams)์ ๋๋ค๋ฅผ ํ์ฉํ ์ ์๋ ๊ธฐ์ ์ค ํ๋.
-๋ฐฐ์ด ๋๋ ์ปฌ๋ ์ ์ธ์คํด์ค์ ํ๋ ์ด์์ ํจ์๋ก ๋ฐ์ดํฐ๋ฅผ ํํฐ๋ง ๋ฐ ๊ฐ๊ณต
-๋๋ค์ ํ์ฉ > ๊ฐ๊ฒฐ์ฑ
-ํจ์ํ์ผ๋ก ์ฒ๋ฆฌ
- Filter
- findFirst() vs findAny()
1. Stream์ ์ง๋ ฌ๋ก ์ฒ๋ฆฌํ ๋ ์ฐจ์ด์ X
2. Stream์ ๋ณ๋ ฌ(parallel())๋ก ์ฒ๋ฆฌํ ๋
findFirst() : ์ฌ๋ฌ ์์๊ฐ ์กฐ๊ฑด์ ๋ถํฉํด๋ Stream์ ๊ฐ์ฅ ์์ ์๋ ์์๋ฅผ ๋ฆฌํด
findAny() : Multi thread์์ Stream์ ์ฒ๋ฆฌํ ๋ ๊ฐ์ฅ ๋จผ์ ์ฐพ์ ์์๋ฅผ ๋ฆฌํด
@Override
public Optional<Member> findByName(String name) {
return store.values().stream()
.filter(member -> member.getName().equals(name))
.findAny();
}
์ด ์ ๋ฌธ ์ฝ๋์๋ ๋ฐฐ์ธ๊ฒ ์ฐธ ๋ง๋ค..!
๐งโ๏ธํ์ ๋ฆฌํฌ์งํ ๋ฆฌ ํ ์คํธ ์ผ์ด์ค ์์ฑ
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.Optional;
import static org.assertj.core.api.Assertions.*;
class MemoryMemberRepositoryTest {
MemoryMemberRepository repository = new MemoryMemberRepository();
@AfterEach
public void afterEach() {
repository.clearStore();
}
@Test
public void save() {
//given
Member member = new Member();
member.setName("spring");
//when
repository.save(member);
//then
Member result = repository.findById(member.getId()).get();
assertThat(result).isEqualTo(member);
}
@Test
public void findByName() {
//given
Member member1 = new Member();
member1.setName("spring1");
repository.save(member1);
Member member2 = new Member();
member2.setName("spring2");
repository.save(member2);
//when
Member result = repository.findByName("spring1").get();
//then
assertThat(result).isEqualTo(member1);
}
@Test
public void findAll() {
//given
Member member1 = new Member();
member1.setName("spring1");
repository.save(member1);
Member member2 = new Member();
member2.setName("spring2");
repository.save(member2);
//when
List<Member> result = repository.findAll();
//then
assertThat(result.size()).isEqualTo(2);
}
}
๐๐์ธํ ๋ฆฌ์ ์ด ๊ฟํ shift+f6 ์ด๋ฆ ํ๋ฒ์ ๋ฐ๊พธ๊ธฐ
๐๐@AfterEach : ๊ฐ ํ ์คํธ๊ฐ ์ข ๋ฃ๋ ๋ ๋ง๋ค ์ด ๊ธฐ๋ฅ์ ์คํํ๋ค. ์ฌ๊ธฐ์๋ ๋ฉ๋ชจ๋ฆฌ DB์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ๋ค.
ํ ์คํธ๋ ๊ฐ๊ฐ ๋ ๋ฆฝ์ ์ผ๋ก ์คํ๋์ด์ผ ํ๋ค. ํ ์คํธ ์์์ ์์กด๊ด๊ณ๊ฐ ์๋ ๊ฒ์ ์ข์ ํ ์คํธ๊ฐ ์๋๋ค
๐๐Repository๋ฅผ ์ธํฐํ์ด์ค๋ก ์ค๊ณ : MemberRepository ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ๊ตฌํ์ฒด์ ๋ณ๊ฒฝ์ด ์ฝ๋ค.
Q. ์๋ฃํ ๋ณ๊ฒฝํ ์ด์ ๋ ๋ฌด์์ธ๊ฐ์? (MemberRepository > MemoryMemberRepository)
A. MemberRepository๊ฐ ์ธํฐํ์ด์ค๋ฅผ ์ฐธ์กฐํ๋ ๊ฒฝ์ฐ ์ธํฐํ์ด์ค์์ ์ ์๋ ๋ฉ์๋๋ง ์ฌ์ฉํ ์ ์๋๋ฐ์. ์ถ๊ฐํ ๋ฉ์๋์ธ clearStore()๊ฐ ์ธํฐํ์ด์ค๊ฐ ์๋ ์ด๊ฒ์ ๊ตฌํํ ํด๋์ค์ ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ์ฐพ์ง ๋ชปํด์ MemoryMemberRepository ํด๋์ค๋ฅผ ์ฐธ์กฐํ๋๋ก ๋ฐ๊ฟ์ค ๊ฑฐ์์.
์ถ์ฒ : ์คํ๋ง ์ ๋ฌธ - ์ฝ๋๋ก ๋ฐฐ์ฐ๋ ์คํ๋ง ๋ถํธ, ์น MVC, DB ์ ๊ทผ ๊ธฐ์