-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
108516b
commit 009d430
Showing
2 changed files
with
211 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
210 changes: 210 additions & 0 deletions
210
developLog/programming-lanuage/java/effective-java/7/item-45.md
This file contains 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,210 @@ | ||
# item 45 : μ€νΈλ¦Όμ μ£Όμν΄μ μ¬μ©νλΌ | ||
|
||
μ€νΈλ¦Όμ΄λ μλ° 8λΆν° **λ€λμ λ°μ΄ν° μ²λ¦¬ μμ **(μμ°¨/λ³λ ¬)μ λκ³ μ λμ¨ APIμ΄λ©°, λ κ°μ§ ν΅μ¬μ μΈ μΆμ κ°λ μ μ 곡νλ€. | ||
|
||
μ€νΈλ¦Όμ μνλ κ²°κ³Όλ₯Ό μμ±νκΈ° μν΄ νμ΄νλΌμΈμΌλ‘ μ°κ²°λ μ μλ λ€μν λ©μλλ₯Ό μ§μνλ κ°μ²΄ μνμ€μ΄λ€. λ°μ΄ν°μ νλ¦, μ¦ μ€νΈλ¦Όμ΄ νλ¬κ°λ κ³Όμ μμ λ°μ΄ν°κ° μμ°¨μ μΌλ‘ νλμ© μ¬μ©λκ³ μ¬λΌμ§λ€. | ||
|
||
λμ©λ λ°μ΄ν°λ₯Ό μ²λ¦¬ν λ ν¨μ¨μ λμ΄κΈ° μν΄, μ€ν λ°μ±/μΈλ°μ± κ³Όμ μ΄ νμ μλ `Intstream` κ³Ό κ°μ κΈ°λ³Έν μ€νΈλ¦Όλ μ 곡νλ€. | ||
|
||
> π **μ€νΈλ¦Όμ μΆμ κ°λ **\ | ||
> 1\. μ€νΈλ¦Ό(stream) : λ°μ΄ν° μμμ μ ν νΉμ 무ν μνμ€\ | ||
> 2\. μ€νΈλ¦Ό νμ΄νλΌμΈ(stream pipeline) : μ΄ μμλ€λ‘ μννλ μ°μ° λ¨κ³λ₯Ό νν | ||
#### βοΈ μ€νΈλ¦Ό νμ΄νλΌμΈ <a href="#undefined" id="undefined"></a> | ||
|
||
![](https://velog.velcdn.com/images/semi-cloud/post/8f2e7dd2-405b-4653-bc32-9269a0f7cc59/image.png) | ||
|
||
**μ€νΈλ¦Ό νμ΄νλΌμΈ μ°μ°** | ||
|
||
μ€νΈλ¦Ό νμ΄νλΌμΈμ μμ€ μ€νΈλ¦Όμμ μμν΄ μ’ λ¨ μ°μ°μΌλ‘ λλλ©°, κ·Έ μ¬μ΄μ νλ μ΄μμ μ€κ° μ°μ°μ΄ μμ μ μλ€. | ||
|
||
**1. μ€κ° μ°μ°(Intermediate Operation)**\ | ||
κ° μ€κ° μ°μ°μ **μ€νΈλ¦Όμ μ΄λ ν λ°©μμΌλ‘ λ³ν**νλ μν μ μννλ©°, λͺ¨λ ν μ€νΈλ¦Όμ λ€λ₯Έ μ€νΈλ¦ΌμΌλ‘ λ³ννκ² νμ¬ λ©μλ 체μ΄λμ κ°λ₯νκ² νλ€. μλ₯Ό λ€μ΄, κ° μμμ ν¨μλ₯Ό μ μ©νκ±°λ νΉμ 쑰건μ λ§μ‘± λͺ»νλ μμλ₯Ό κ±Έλ¬λΌ μ μλ€. | ||
|
||
* `filter()`, `map()`, `sorted()` | ||
|
||
**2. μ’ λ¨ μ°μ°(Terminal Operation)**\ | ||
μ’ λ¨ μ°μ°μ λ§μ§λ§ μ€κ° μ°μ°μ΄ λ΄λμ **μ€νΈλ¦Όμ μ΅νμ μ°μ°μ κ°νλ** μν μ νλ€. μλ₯Ό λ€μ΄, μμλ₯Ό μ λ ¬ν΄ μ»¬λ μ μ λ΄κ±°λ νΉμ μμλ₯Ό νλ μ ννλ μμ΄λ€. | ||
|
||
* `forEach()`, `collect()`, `match()`, `count()`, `reduce()` | ||
|
||
```java | ||
List<Integer> transactionsIds = | ||
transactions.stream() | ||
.filter(t -> t.getType() == Transaction.GROCERY) | ||
.sorted(comparing(Transaction::getValue).reversed()) | ||
.map(Transaction::getId) | ||
.collect(toList()); | ||
``` | ||
|
||
![](https://velog.velcdn.com/images/semi-cloud/post/7f73e3a6-941c-4c4d-af7e-b3a19d1b921e/image.png) | ||
|
||
[https://www.geeksforgeeks.org/java-8-stream-tutorial/](https://www.geeksforgeeks.org/java-8-stream-tutorial/) | ||
|
||
#### βοΈ μ€νΈλ¦Ό νμ΄νλΌμΈ νΉμ§ <a href="#undefined" id="undefined"></a> | ||
|
||
**1. μ§μ° νκ°(lazy evaluation)** | ||
|
||
λ¨Όμ μ§μ°μ΄λ **κ²°κ³Όκ°μ΄ νμν λκΉμ§ κ³μ°μ λ¦μΆλ** κΈ°λ²μ μλ―Ένλ€. μ΄λ κ² ν¨μΌλ‘μ¨ μ΄λ λΆλΆμμ κ°μ₯ ν° μ΄μ΅μ μ»μ μ μμκΉ? | ||
|
||
> λμ©λμ λ°μ΄ν°μμ, **μ€μ λ‘ νμνμ§ μμ λ°μ΄ν°λ€μ νμνλ κ²μ λ°©μ§**ν΄ μλλ₯Ό λμΌ μ μλ€. μ¦, μ’ λ¨ μ°μ°μ μ°μ΄μ§ μλ λ°μ΄ν° μμλ κ³μ° μ체μ μ°μ΄μ§ μλλ€. κ·Έλ¦¬κ³ μ΄κ²μ `Short-Circuit` λ°©μμ΄λΌ λΆλ₯Έλ€. | ||
![](https://velog.velcdn.com/images/semi-cloud/post/46a80a05-ff1a-4ab6-9e43-88aadb31e8cc/image.png)\ | ||
[https://www.logicbig.com/tutorials/core-java-tutorial/java-util-stream/short-circuiting.html](https://www.logicbig.com/tutorials/core-java-tutorial/java-util-stream/short-circuiting.html) | ||
|
||
μ€νΈλ¦Ό νμ΄νλΌμΈμ μ€ννκ² λλ©΄, `JVM` μ 곧λ°λ‘ μ€νΈλ¦Ό μ°μ°μ μ€νμν€μ§ μλλ€. μ΅μνμΌλ‘ νμμ μΈ μμ λ§ μννκ³ μ κ²μ¬λ₯Ό λ¨Όμ νκ³ , μ΄λ₯Ό λ°νμΌλ‘ μ΅μ ν λ°©λ²μ μ°Ύμλ΄ κ³ννλ€. κ·Έλ¦¬κ³ κ·Έ κ³νμ λ°λΌ κ°λ³ μμμ λν μ€νΈλ¦Ό μ°μ°μ μννλ€. | ||
|
||
μλ₯Ό λ€μ΄, `10000` κ°μ λ°μ΄ν°μ€μ κΈΈμ΄κ° 5κ° λλ λ¬Έμμ΄μμ κ°μ₯ μνλ²³μμΌλ‘ μμ μλ 2κ°μ λ¬Έμμ΄λ§ κ°μ§κ³ μ€κ³ μΆλ€κ³ νμ. μ§μ° νκ°κ° μμ΄ μμλλ‘ λ°λ‘ λμνλ€λ©΄, `10000` κ°μ λ°μ΄ν°λ₯Ό λͺ¨λ μνν΄μΌ νμ κ²μ΄λ€. | ||
|
||
νμ§λ§ μ΄μ§νΌ μ΅μ’ μ μΌλ‘ 2κ°λ§ νμνλ©΄ λλλ° μ 체 λ°μ΄ν°λ₯Ό λ€ λ³Ό νμκ° μμκΉ? | ||
|
||
1. `limit` μ¬μ© O\ | ||
![](https://velog.velcdn.com/images/semi-cloud/post/d762d983-e0dd-4f8f-a535-c7fef2c58483/image.png) | ||
2. `limit` μ¬μ© X\ | ||
![](https://velog.velcdn.com/images/semi-cloud/post/ee8b44f3-0172-4b03-bcd6-f3979d65f342/image.png) | ||
|
||
κ²°κ³Όλ₯Ό λ΄λ³΄μ. `limit(n)` μ°μ°μ΄ λ΄λΆμ μΌλ‘ μμ μκ² λλ¬ν μμκ° `n` κ°κ° λμμ λ μ€νΈλ¦Ό λ΄ λ€λ₯Έ μμλ€μ λν΄ λ μ΄μ μννμ§ μκ³ νμΆνλλ‘ λ§λ€μκΈ° λλ¬Έμ, κΈΈμ΄κ° `5`κ° λλ λ°μ΄ν° `4` κ°κ° μλ, 맨 μμ `2` κ° λ°μ΄ν°κ° μΆλ ₯λ κ²μ λ³Ό μ μλ€.\ | ||
![](https://velog.velcdn.com/images/semi-cloud/post/bc56f393-72aa-492e-b91c-c14269478d0e/image.png) | ||
|
||
**μμΈ μ¬ν: Stateful operations** | ||
|
||
μ΄λ¬ν μ§μ° νκ° νΉμ±μΌλ‘ μΈν΄, μ°λ¦¬λ **무ν μ€νΈλ¦Ό**μ λ€λ£° μ μκ² λλ€. | ||
|
||
무ν μ€νΈλ¦Όμ μ μ΄μ ν¬κΈ°κ° μ ν΄μ Έ μμ§ μμ λ§νΌ, μ€λ³΅ μ κ±°λ₯Ό νμ§ λͺ»νλ€ . νμ§λ§ `limit()` κ³Ό κ°μ `short-circuit` μ°μ°μ ν΅ν΄ μ ν μ€νΈλ¦ΌμΌλ‘ λ³ν€ν¨μΌλ‘μ¨ κ°λ₯ν΄μ§λ€. | ||
|
||
> π **μ ν μ€νΈλ¦Ό vs 무ν μ€νΈλ¦Ό**\ | ||
> 1\. μ ν μ€νΈλ¦Ό : μμ±ν λ ν¬κΈ°κ° μ ν΄μ Έ μλ μ€νΈλ¦Ό | ||
> | ||
> ```java | ||
> IntStream ints(long streamsize, int begin, int end) | ||
> ``` | ||
> | ||
> 2.무ν μ€νΈλ¦Ό : 무νν ν¬κΈ°λ‘ κ°μ κ°μ§λ μ€νΈλ¦Ό | ||
> | ||
> ```java | ||
> IntStream ints(int begin, int end) | ||
> ``` | ||
μ΄μ²λΌ μ€λ³΅μ μ κ±°νλ `distinct()` λ, μ 체 λ°μ΄ν°λ₯Ό μ λ ¬νλ `sort()` μ°μ°λ€μ `Stateful` μ°μ°μ΄λΌ νλ€. νμ§λ§ μ΄λ μ§μ° νκ°λ₯Ό 무ν¨νμν€κ³ , κ²°κ³Όλ₯Ό μμ±νκΈ° μ μ μ 체 λ°μ΄ν°λ₯Ό νμνλ κ²°κ³Όλ₯Ό μ΄λνλ€. μμλ₯Ό λ΄λ³΄μ. | ||
![](https://velog.velcdn.com/images/semi-cloud/post/7b5a3dc1-fcb6-497c-9976-71acf246605e/image.png) | ||
`limit()` μ κ±Έμ΄μ£Όμμμλ, `sorted()` μΌλ‘ μΈν΄ κΈΈμ΄κ° `5`κ° λλ λͺ¨λ λ€κ°μ λ°μ΄ν°λ€μ νμν νμκ° μ겨 μ§μ° νκ°κ° μ΄λ£¨μ΄μ§μ§ μμ κ²μ λ³Ό μ μλ€. | ||
![](https://velog.velcdn.com/images/semi-cloud/post/e60f5506-cedb-4c8c-8b13-ee1318496f19/image.png) | ||
**2. μμ°¨μ±** | ||
κΈ°λ³Έμ μΌλ‘ μ€νΈλ¦Ό νμ΄νλΌμΈμ μμ°¨μ μΌλ‘ μνλλ€. νμ΄νλΌμΈμ λ³λ ¬λ‘ μ€ννλ €λ©΄, νμ΄νλΌμΈμ ꡬμ±νλ μ€νΈλ¦Ό μ€ νλμμ `parallel` λ©μλλ₯Ό νΈμΆν΄μ£ΌκΈ°λ§ νλ©΄ λλ, ν¨κ³Όλ₯Ό λ³Ό μ μλ μν©μ λ§μ§ μλ€. | ||
#### βοΈ λ°λ³΅λ¬Έμ μ€νΈλ¦ΌμΌλ‘ 무쑰건 λ°κΎΈλκ²μ΄ μ’μκΉ? <a href="#undefined" id="undefined"></a> | ||
μ€νΈλ¦Όμ μ λλ‘ μ¬μ©νλ©΄ νλ‘κ·Έλ¨μ΄ μ§§κ³ κΉλν΄μ§μ§λ§, μλͺ» μ¬μ©νλ©΄ μ½κΈ° μ΄λ ΅κ³ μ μ§λ³΄μκ° νλ€λ€. κ·Έλ λ€λ©΄ λ°©λ²μ? | ||
**1. λͺ¨λ λ°λ³΅λ¬Έμ μ€νΈλ¦ΌμΌλ‘ λ°κΎΈκΈ° 보λ€, λ°λ³΅λ¬Έκ³Ό μ€νΈλ¦Όμ μ μ ν μ‘°ν©νμ.** | ||
λ€μ μ½λμ μμλ₯Ό λ€μ΄ μ€λͺ ν΄λ³΄κ² λ€. μ΄ νλ‘κ·Έλ¨μ, μ¬μ νμΌμμ λ¨μ΄λ₯Ό μ½μ΄ μ¬μ©μκ° μ§μ ν λ¬Έν±κ°λ³΄λ€ μμ μκ° λ§μ μλκ·Έλ¨ κ·Έλ£Ήμ μΆλ ₯νλ€. (μ² μλ₯Ό ꡬμ±νλ μνλ²³μ΄ κ°κ³ μμλ§ λ€λ₯Έ λ¨μ΄) | ||
```java | ||
public class Anagrams { | ||
public static void main(String[] args) throws IOException { | ||
File dictionary = new File(args[0]); | ||
int minGroupSize = Interger.parseInt(args[1]); | ||
Map<String, Set<String>> groups = new HashMap<>(); | ||
try(Scanner s = new Scanner(dictionary)){ | ||
while(s.hasNext()){ | ||
String word = s.next(); | ||
groups.computeIfAbsent(alphabetize(word), (unused) -> new TreeSet<>()).add(word); | ||
} | ||
} | ||
for(Set<String> group : groups.values()) | ||
if(group.size() >= minGroupSize) | ||
System.out.println(group.size() + ":" + group); | ||
} | ||
public static String alphabetie(String s){ | ||
char[] a = s.toCharArray(); | ||
Arrays.sort(a); | ||
return new String(a); | ||
} | ||
} | ||
``` | ||
* `computeIfAbsent()` : 맡 μμ ν€κ° μλ€λ©΄ 맀νλ κ°μ λ°ννκ³ μλ€λ©΄ 건λ€μ§ ν¨μ κ°μ²΄λ₯Ό ν€μ μ μ©νμ¬ κ°μ κ³μ°ν λ€μ ν€μ κ°μ 맀νν΄λκ³ , κ³μ°λ κ°μ λ°ν | ||
```java | ||
try (Stream<String> words = Files.lines(dictionary)) { | ||
words.collect( | ||
groupingBy(word -> word.chars().sorted() | ||
.collect(StringBuilder::new, | ||
(sb, c) -> sb.append((char) c), | ||
StringBuilder::append).toString())) | ||
.values().stream() | ||
.filter(group -> group.size() >= minGroupSize) | ||
.map(group -> group.size() + ": " + group) | ||
.forEach(System.out::println); | ||
} | ||
} | ||
} | ||
``` | ||
μ€νΈλ¦Όμ κ³Όνκ² νμ©νμ¬, μ¬μ νμΌ μ¬λ λΆλΆμ μ μΈνκ³ νλ‘κ·Έλ¨ μ μ²΄κ° λ¨ νλμ ννμμΌλ‘ μ²λ¦¬λκ³ μλ€. μ΄μ²λΌ μ€νΈλ¦Όμ κ³Όμ©νλ©΄ νλ‘κ·Έλ¨μ΄ μ½κ±°λ μ μ§λ³΄μνκΈ° μ΄λ €μμ§λ€. | ||
**μ€νΈλ¦Όμ μ μ νκ² νμ©νκΈ°** | ||
```java | ||
try (Stream<String> words = Files.lines(dictionary)) { | ||
words.collect(groupingBy(word -> alphabetize(word))) | ||
.values().stream() | ||
.filter(group -> group.size() >= minGroupSize) | ||
.forEach(g -> System.out.println(g.size() + ": " + g)); | ||
} | ||
``` | ||
`alphabetize()` κ³Ό κ°μ μΈλΆ ꡬνμ μ£Ό νλ‘κ·Έλ¨ λ‘μ§ λ°μΌλ‘ λΉΌλ΄ μ 체μ μΈ κ°λ μ±μ λμλ€. μ΄μ²λΌ λμ°λ―Έ λ©μλλ₯Ό μ μ ν νμ©νλ μΌμ μ€μμ±μ μΌλ° λ°λ³΅ μ½λμμ보λ€λ μ€νΈλ¦Ό νμ΄νλΌμΈμμ ν¨μ¬ 컀μ§λ€. | ||
> π λλ€μμλ νμ μ΄λ¦μ μμ£Ό μλ΅νλ―λ‘, 맀κ°λ³μμ μ΄λ¦μ μ μ§μ΄μΌ μ€νΈλ¦Ό νμ΄νλΌμΈμ κ°λ μ±μ΄ μ μ§ν μ μλ€. | ||
**2.char κ°μ μ²λ¦¬ν λλ μ€νΈλ¦Όμ μ¬μ©νμ§ λ§μ.** | ||
μλ°λ κΈ°λ³Έ νμ μΈ `char` μ© μ€νΈλ¦Όμ μ§μνμ§ μλλ€. λ°λΌμ μλ μ½λλ₯Ό μ€νμμΌλ³΄λ©΄ μ μκ°μ΄ μΆλ ₯λλ€. μ°Έκ³ λ‘ `boolean[]`, `byte[]`, `short[]`, `char[]`, `float[]` λ ν΄λΉ νμ μ κΈ°λ³Έν μ€νΈλ¦Όμ΄ μ‘΄μ¬νμ§ μλλ€. | ||
```java | ||
"Hello World!".chars().forEach(System.out::print); // μ μκ°μ΄ μΆλ ₯λ¨ : 739488237102.. | ||
``` | ||
#### βοΈ μ€νΈλ¦Όμ μ μ ν νμ© <a href="#undefined" id="undefined"></a> | ||
μ€νΈλ¦Ό νμ΄νλΌμΈμ λνμ΄ λλ κ³μ°μ μ£Όλ‘ ν¨μ κ°μ²΄(λλ€/λ©μλ μ°Έμ‘°)λ‘ νννκ³ λ°λ³΅ μ½λμλ μ½λ λΈλ‘μ μ¬μ©ν΄ νννλ€. | ||
**μ€νΈλ¦ΌμΌλ‘ μ²λ¦¬νκΈ° νλ κ²½μ°** | ||
μ€νΈλ¦Όκ³Ό ν¨μ κ°μ²΄λ‘λ ν μ μμ§λ§, μ½λ λΈλ‘μΌλ‘λ ν μ μλ κ²½μ°λ₯Ό ꡬλΆνλ©΄ λ€μκ³Ό κ°λ€. | ||
1. μ½λ λΈλ‘μμλ λ²μ μμ μ§μλ³μλ₯Ό μ½κ³ μμ ν μ μλ€. νμ§λ§ λλ€μμλ μ¬μ€μ `final` μΈ λ³μλ§ μ½μ μ μκ³ , μ§μλ³μ μμ μ λΆκ°λ₯νλ€. | ||
2. μ½λ λΈλ‘μμλ `return` / `break` / `continue` λ¬ΈμΌλ‘ λΈλ‘μ νλ¦μ μ μ΄νκ±°λ, λ©μλ μ μΈμ λͺ μλ κ²μ¬ μμΈλ₯Ό λμ§ μ μλ€. νμ§λ§ λλ€λ λΆκ°λ₯νλ€. | ||
**μ€νΈλ¦Όμ μ μ©νκΈ° μ’μ κ²½μ°** | ||
1. μμλ€μ μνμ€λ₯Ό μΌκ΄λκ² λ³νν΄μΌ νλ κ²½μ° : `map()` | ||
2. μμλ€μ μνμ€λ₯Ό νν°λ§ ν΄μΌ νλ κ²½μ° : `filter()` | ||
3. μμλ€μ μνμ€λ₯Ό νλμ μ°μ°μ μ¬μ©ν΄ κ²°ν©ν΄μΌ νλ κ²½μ°(λνκΈ°, μ°κ²°νκΈ°, μ΅μκ° κ΅¬νκΈ° λ±) : | ||
4. μμλ€μ μνμ€λ₯Ό 컬λ μ μ λͺ¨μΌλ κ²½μ°(곡ν΅λ μμ±μ κΈ°μ€μΌλ‘) : `collect()` | ||
5. μμλ€μ μνμ€μμ νΉμ 쑰건μ λ§μ‘±νλ μμλ₯Ό μ°Ύμ κ²½μ° : `filter()` | ||
#### βοΈ μ€νΈλ¦ΌμΌλ‘ μ²λ¦¬νκΈ° μ΄λ €μ΄ κ²½μ° <a href="#undefined" id="undefined"></a> | ||
ν λ°μ΄ν°κ° νμ΄νλΌμΈμ μ¬λ¬ λ¨κ³λ₯Ό ν΅κ³Όν΄μΌν λ, μ΄ λ°μ΄ν°μ κ° λ¨κ³μμμ κ°λ€μ λμμ μ κ·Όνλ κ²½μ°μλ μ€νΈλ¦Όμ μ¬μ©νκΈ° νλ€λ€. νμ΄νλΌμΈμ μΌλ¨ ν κ°μ λ€λ₯Έ κ°μ 맀ννκ³ λλ©΄ μλμ κ°μ μλ ꡬ쑰μ΄κΈ° λλ¬Έμ΄λ€. | ||
> π **ν΅μ¬ μ 리**\ | ||
> μ€νΈλ¦Όκ³Ό λ°λ³΅ μ€ μ΄λμͺ½μ΄ λμμ§ νμ νκΈ° μ΄λ ΅λ€λ©΄, λ λ€ ν μ€νΈν΄λ³΄κ³ λ λμ μͺ½μ ννλ κ²μ΄ μ’λ€. | ||
> μΆμ² λ° μ°Έκ³ [https://www.logicbig.com/tutorials/core-java-tutorial/java-util-stream/short-circuiting.html](https://www.logicbig.com/tutorials/core-java-tutorial/java-util-stream/short-circuiting.html)\ | ||
> [https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#Statelessness](https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#Statelessness)\ | ||
> [https://bugoverdose.github.io/development/stream-lazy-evaluation/](https://bugoverdose.github.io/development/stream-lazy-evaluation/) | ||
> | ||
> [https://velog.io/@semi-cloud/Effective-Java-%EC%95%84%EC%9D%B4%ED%85%9C-45-%EC%8A%A4%ED%8A%B8%EB%A6%BC%EC%9D%80-%EC%A3%BC%EC%9D%98%ED%95%B4%EC%84%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EB%9D%BC](https://velog.io/@semi-cloud/Effective-Java-%EC%95%84%EC%9D%B4%ED%85%9C-45-%EC%8A%A4%ED%8A%B8%EB%A6%BC%EC%9D%80-%EC%A3%BC%EC%9D%98%ED%95%B4%EC%84%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EB%9D%BC) | ||
> | ||
> [https://kdg-is.tistory.com/378](https://kdg-is.tistory.com/378) |