-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feat : step3 #4243
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
feat : step3 #4243
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,66 +1,55 @@ | ||
| package lotto; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Arrays; | ||
| import java.util.Collections; | ||
| import java.util.HashSet; | ||
| import java.util.List; | ||
| import java.util.Set; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| public class Lotto { | ||
| private static final int SIZE = 6; | ||
| private static final int MIN = 1; | ||
| private static final int MAX = 45; | ||
| private static final int LOTTO_SIZE = 6; | ||
|
|
||
| private final Set<Integer> numbers; | ||
| private final Set<LottoNumber> numbers; | ||
|
|
||
| public Lotto(List<Integer> numbers) { | ||
| validateSize(numbers); | ||
| validateRange(numbers); | ||
| validateUnique(numbers); | ||
| this.numbers = Set.copyOf(numbers); | ||
| } | ||
|
|
||
| public Lotto(int... numbers) { | ||
| this(Arrays.stream(numbers).boxed().collect(Collectors.toList())); | ||
| } | ||
|
|
||
| public List<Integer> numbers() { | ||
| return numbers.stream() | ||
| .sorted() | ||
| .collect(Collectors.toList()); | ||
| } | ||
|
|
||
| public boolean contains(int number) { | ||
| return numbers.contains(number); | ||
| this(toLottoNumbers(numbers)); | ||
| } | ||
|
|
||
| public int matchCount(Lotto winning) { | ||
| return (int) numbers.stream() | ||
| .filter(winning::contains) | ||
| .count(); | ||
| private Lotto(Set<LottoNumber> numbers) { | ||
| validate(numbers); | ||
| this.numbers = Set.copyOf(numbers); | ||
| } | ||
|
|
||
| private void validateSize(List<Integer> numbers) { | ||
| if (numbers.size() != SIZE) { | ||
| throw new IllegalArgumentException("로또 번호는 6개여야 한다."); | ||
| private static Set<LottoNumber> toLottoNumbers(List<Integer> numbers) { | ||
| Set<LottoNumber> result = new HashSet<>(); | ||
| for (int n : numbers) { | ||
| result.add(LottoNumber.from(n)); | ||
| } | ||
| return result; | ||
| } | ||
|
|
||
| private void validateRange(List<Integer> numbers) { | ||
| if (numbers.stream().anyMatch(this::isOutOfRange)) { | ||
| throw new IllegalArgumentException("로또 번호는 1~45 범위여야 한다."); | ||
| private void validate(Set<LottoNumber> numbers) { | ||
| if (numbers.size() != LOTTO_SIZE) { | ||
| throw new IllegalArgumentException("로또 번호는 중복 없이 " + LOTTO_SIZE + "개여야 합니다."); | ||
| } | ||
| } | ||
|
|
||
| private boolean isOutOfRange(int number) { | ||
| return number < MIN || number > MAX; | ||
| public boolean contains(LottoNumber number) { | ||
| return numbers.contains(number); | ||
| } | ||
|
|
||
| private void validateUnique(List<Integer> numbers) { | ||
| if (new HashSet<>(numbers).size() != SIZE) { | ||
| throw new IllegalArgumentException("로또 번호는 중복될 수 없다."); | ||
| public int matchCount(Lotto other) { | ||
| int count = 0; | ||
| for (LottoNumber n : numbers) { | ||
| if (other.contains(n)) count++; | ||
| } | ||
| return count; | ||
| } | ||
|
|
||
| public List<Integer> numbers() { | ||
| return numbers.stream() | ||
| .map(LottoNumber::value) | ||
| .sorted() | ||
| .collect(Collectors.toList()); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| package lotto; | ||
|
|
||
| import java.util.Map; | ||
| import java.util.Objects; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
|
|
||
| public class LottoNumber { | ||
| private static final int MIN = 1; | ||
| private static final int MAX = 45; | ||
|
|
||
| private static final Map<Integer, LottoNumber> CACHE = new ConcurrentHashMap<>(); | ||
|
|
||
| private final int value; | ||
|
|
||
| private LottoNumber(int value) { | ||
| this.value = value; | ||
| } | ||
|
|
||
| public static LottoNumber from(int value) { | ||
| validateRange(value); | ||
| return CACHE.computeIfAbsent(value, LottoNumber::new); | ||
| } | ||
|
|
||
| private static void validateRange(int value) { | ||
| if (value < MIN || value > MAX) { | ||
| throw new IllegalArgumentException("로또 번호는 " + MIN + " ~ " + MAX + " 사이여야 합니다. value=" + value); | ||
| } | ||
| } | ||
|
|
||
| public int value() { | ||
| return value; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean equals(Object o) { | ||
| if (this == o) return true; | ||
| if (!(o instanceof LottoNumber)) return false; | ||
| return value == ((LottoNumber) o).value; | ||
| } | ||
|
|
||
| @Override | ||
| public int hashCode() { | ||
| return Integer.hashCode(value); | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| return String.valueOf(value); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package lotto; | ||
|
|
||
| import java.util.HashSet; | ||
| import java.util.List; | ||
| import java.util.Set; | ||
|
|
||
| public class Lottos { | ||
| private final List<Lotto> values; | ||
|
|
||
| public Lottos(List<Lotto> values) { | ||
| this.values = List.copyOf(values); | ||
| } | ||
|
|
||
| public List<Lotto> values() { | ||
| return values; | ||
| } | ||
|
|
||
| public int size() { | ||
| return values.size(); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package lotto; | ||
|
|
||
| public class MatchResult { | ||
| private final int matchCount; | ||
| private final boolean bonusMatched; | ||
|
|
||
| public MatchResult(int matchCount, boolean bonusMatched) { | ||
| this.matchCount = matchCount; | ||
| this.bonusMatched = bonusMatched; | ||
| } | ||
|
|
||
| public int matchCount() { | ||
| return matchCount; | ||
| } | ||
|
|
||
| public boolean bonusMatched() { | ||
| return bonusMatched; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,50 +1,54 @@ | ||
| package lotto; | ||
|
|
||
| import java.util.Arrays; | ||
|
|
||
| import lotto.MatchResult; | ||
|
|
||
| public enum Rank { | ||
| FIRST(6, 2_000_000_000, "6개 일치"), | ||
| THIRD(5, 1_500_000, "5개 일치"), | ||
| FOURTH(4, 50_000, "4개 일치"), | ||
| FIFTH(3, 5_000, "3개 일치"), | ||
| MISS(0, 0, ""); | ||
| FIRST(6, false, 2_000_000_000, "6개 일치", 5), | ||
| SECOND(5, true, 30_000_000, "5개 일치, 보너스 볼 일치", 4), | ||
| THIRD(5, false, 1_500_000, "5개 일치", 3), | ||
| FOURTH(4, false, 50_000, "4개 일치", 2), | ||
| FIFTH(3, false, 5_000, "3개 일치", 1), | ||
| MISS(0, false, 0, "", 0); | ||
|
|
||
| private final int matchCount; | ||
| private final long prize; | ||
| private final boolean bonusNeeded; | ||
| private final int prize; | ||
| private final String description; | ||
| private final int displayOrder; | ||
|
|
||
| Rank(int matchCount, long prize, String description) { | ||
| Rank(int matchCount, boolean bonusNeeded, int prize, String description, int displayOrder) { | ||
| this.matchCount = matchCount; | ||
| this.bonusNeeded = bonusNeeded; | ||
| this.prize = prize; | ||
| this.description = description; | ||
| this.displayOrder = displayOrder; | ||
| } | ||
|
|
||
| public int matchCount() { | ||
| return matchCount; | ||
| public static Rank of(MatchResult result) { | ||
| int matchCount = result.matchCount(); | ||
| boolean bonusMatched = result.bonusMatched(); | ||
|
|
||
| if (matchCount == 6) return FIRST; | ||
| if (matchCount == 5) return bonusMatched ? SECOND : THIRD; | ||
| if (matchCount == 4) return FOURTH; | ||
| if (matchCount == 3) return FIFTH; | ||
| return MISS; | ||
| } | ||
|
|
||
| public long prize() { | ||
| public int prize() { | ||
| return prize; | ||
| } | ||
|
|
||
| public String description() { | ||
| return description; | ||
| } | ||
|
|
||
| public boolean isWinning() { | ||
| return this != MISS; | ||
| } | ||
|
|
||
| public static Rank of(int matchCount) { | ||
| return Arrays.stream(values()) | ||
| .filter(rank -> rank.matchCount == matchCount) | ||
| .findFirst() | ||
| .orElse(MISS); | ||
| public int displayOrder() { | ||
| return displayOrder; | ||
| } | ||
|
|
||
| public static Rank[] winningRanks() { | ||
| return Arrays.stream(values()) | ||
| .filter(Rank::isWinning) | ||
| .toArray(Rank[]::new); | ||
| return new Rank[]{FIFTH, FOURTH, THIRD, SECOND, FIRST}; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,28 @@ | ||
| package lotto; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.Comparator; | ||
| import java.util.List; | ||
|
|
||
| public class ResultView { | ||
| public void printLottos(List<Lotto> lottos) { | ||
| public void printLottos(Lottos lottos) { | ||
| System.out.println(lottos.size() + "개를 구매했습니다."); | ||
| lottos.forEach(lotto -> System.out.println(lotto.numbers())); | ||
| lottos.values().forEach(lotto -> System.out.println(lotto.numbers())); | ||
| } | ||
|
|
||
| public void printStatistics(WinningStatistics stats, Money money) { | ||
| System.out.println(); | ||
| System.out.println("당첨 통계"); | ||
| System.out.println("---------"); | ||
|
|
||
| for (Rank rank : Rank.winningRanks()) { | ||
| System.out.println(rank.description() + " (" + rank.prize() + "원)- " | ||
| + stats.countOf(rank) + "개"); | ||
| } | ||
| Arrays.stream(Rank.winningRanks()) | ||
| .sorted(Comparator.comparingInt(Rank::displayOrder)) | ||
| .forEach(rank -> printRank(stats, rank)); | ||
|
|
||
| System.out.println("총 수익률은 " + stats.profitRate(money) + "입니다."); | ||
| } | ||
|
|
||
| private void printRank(WinningStatistics stats, Rank rank) { | ||
| System.out.println(rank.description() + " (" + rank.prize() + "원)- " + stats.countOf(rank) + "개"); | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
상황
위 요구사항을 서버에서 생성되는 LottoNumber의 인스턴스의 갯수는?
1 * 5장 * 6개 숫자/1장 * 1만명 = 30만개이다.
동시에 생성되는 인스턴스 갯수가 너무 많다.
인스턴스 갯수를 줄일 수 있는 방법은?
로또 숫자 값을 LottoNumber 객체로 래핑하는 경우 매번 인스턴스가 생성되기 때문에 인스턴스의 갯수가 너무 많아져 성능이 떨어질 수 있다.
LottoNumber 인스턴스를 생성한 후 재사용할 수 있도록 구현한다.
힌트 : Map과 같은 곳에 인스턴스를 생성한 후 재사용하는 방법을 찾아본다.