item 47 JihoonKim - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki
์ผ๋ จ์ ์์(์์ ์ํ์ค)๋ฅผ ๋ฆฌํดํ ๋์ ํ์
- Collection, Set, List ๊ฐ์ ์ปฌ๋ ์ ์ธํฐํ์ด์ค(๊ธฐ๋ณธ)
- Iterable
- ๋ฐฐ์ด(์ฑ๋ฅ์ ๋ฏผ๊ฐํ ์ํฉ)
- ์คํธ๋ฆผ
์คํธ๋ฆผ์ด ๋์ ๋๋ฉด์ ๋ฆฌํด ํ์ ์ ์ ํ์ด ๋ณต์กํด์ก๋ค.
์คํธ๋ฆผ์ Iterable์ ํ์ฅ(extends)ํ์ง ์์ ๋ฐ๋ณต(iteration)์ ์ง์ํ์ง ์๋๋ค. ๋ฐ๋ผ์, ์คํธ๋ฆผ๊ณผ ๋ฐ๋ณต์ ์๋ง๊ฒ ์กฐํฉํด์ผ ์ข์ ์ฝ๋๊ฐ ๋์จ๋ค.
// Stream์ iterator ๋ฉ์๋์ ๋ฉ์๋ ์ฐธ์กฐ๋ฅผ ๊ฑด๋ค ์คํธ๋ฆผ์ ๋ฐ๋ณต์ ์ง์ - Compile ์๋ฌ(ํ์
์ถ๋ก ํ๊ณ)
for (ProcessHandle p : ProcessHandle.allProcesses()::iterator) {
// process ์ฒ๋ฆฌ
}
// Stream์ iterator ๋ฉ์๋์ ๋ฉ์๋ ์ฐธ์กฐ๋ฅผ ๊ฑด๋ค์ด ์คํธ๋ฆผ์ ๋ฐ๋ณต์ ์ง์ - ์คํธ๋ฆผ ๋ฐ๋ณต์ ์ํ '๋์ฐํ' ์ฐํ ๋ฐฉ๋ฒ
for (ProcessHandle p : (Iterable<ProcessHandle>) ProcessHandle.allProcesses()::iterator) {
// process ์ฒ๋ฆฌ
}
์ด๋ํฐ ๋ฉ์๋ ์์ฑ์ ํตํด ๊ฐ์ ๊ฐ๋ฅํ๋ค.
// Stream<E>๋ฅผ Iterable<E>๋ก ์ค๊ฐํด์ฃผ๋ ์ด๋ํฐ
public static <E> Iterable<E> iterableOf(Stream<E> stream) {
return stream::iterator;
}
for (ProcessHandle p : iterableOf(ProcessHandle.allProcesses())) {
// process ์ฒ๋ฆฌ
}
// Iterable<E>๋ฅผ Stream<E>๋ก ์ค๊ฐํด์ฃผ๋ ์ด๋ํฐ
public static <E> Stream<E> streamOf(Iterable<E> iterable) {
return StreamSupport.stream(iterable.spliterator(), false); // 2nd param์ parallel ์ฌ๋ถ
}
๊ณต๊ฐ API๋ฅผ ์์ฑํ๋ค๋ฉด ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ ์ฌ์ฉ์์ ๋ฐ๋ณต๋ฌธ ์ฌ์ฉ์ ๋ชจ๋๋ฅผ ๋ฐฐ๋ คํด์ผ ํ๋ค.
Collection ์ธํฐํ์ด์ค๋ Iterable์ ํ์ ํ์
์ด๊ณ stream ๋ฉ์๋๋ ์ ๊ณตํ๋ ๋ฐ๋ณต๊ณผ ์คํธ๋ฆผ์ ๋์์ ์ง์ํ๋ค.
๋ฐ๋ผ์, ์์ ์ํ์ค๋ฅผ ๋ฆฌํดํ๋ ๊ณต๊ฐ API์ ๋ฆฌํด ํ์
์๋ ์ผ๋ฐ์ ์ผ๋ก Collection ๋๋ ๊ทธ ํ์ ํ์
์ ์ฐ๋ ๊ฒ ์ต์ ์ด๋ค.
ํ์ง๋ง, ๋จ์ง ์ปฌ๋ ์
์ ๋ฆฌํดํ๋ค๋ ์ด์ ๋ก ๋ฉ์น ํฐ ์ํ์ค๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ ค์๋ ์ ๋๋ค.
๋ฆฌํดํ ์ํ์ค๊ฐ ํฌ์ง๋ง ํํ์ ๊ฐ๊ฒฐํ๊ฒ ํ ์ ์๋ค๋ฉด ์ ์ฉ Collection์ ๊ตฌํํ๋ ๋ฐฉ์๋ ์๊ฐํด๋ณด์.
์ฃผ์ด์ง ์งํฉ์ ๋ฉฑ์งํฉ(ํ ์งํฉ์ ๋ชจ๋ ๋ถ๋ถ์งํฉ์ ์์๋ก ํ๋ ์งํฉ)์ ๋ฆฌํดํ๋ ์ํฉ
์์ ๊ฐ์๊ฐ n๊ฐ ์ด๋ฉด ๋ฉฑ์งํฉ์ ์์ ๊ฐ์๋ 2^n๊ฐ(์ง์๋ฐฐ๋ก ์ฆ๊ฐ)
์ฐธ๊ณ )
{a, b, c}์ ๋ฉฑ์งํฉ์ { {}, {a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {a, b, c} }
AbstractList๋ฅผ ์ด์ฉํ์ฌ ์ปฌ๋ ์ ๊ตฌํ
- ๊ฐ ์์์ ์ธ๋ฑ์ค๋ฅผ ๋นํธ๋ฒกํฐ๋ก ์ฌ์ฉ(n๋ฒ์งธ ๋นํธ ๊ฐ์ ํด๋น ์์๊ฐ n๋ฒ์งธ ์์ ํฌํจ ์ฌ๋ถ)
- 0๋ถํฐ 2^n - 1 ๊น์ง์ ์ด์ง์์์ ๋งคํ
public class PowerSet {
public static final <E> Collection<Set<E>> of(Set<E> s) {
List<E> src = new ArrayList<>(s);
if(src.size() > 30) { // Collection์ ๋ฆฌํด ํ์
์ผ๋ก ์ธ ๋์ ๋จ์
throw new IllegalArgumentException("์งํฉ์ ์์๊ฐ ๋๋ฌด ๋ง์ต๋๋ค(์ต๋ 30๊ฐ).: " + s);
}
return new AbstractList<Set<E>>() {
@Override
public int size() {
return 1 << src.size(); // 2^n
}
@Override
public boolean contains(Object o) {
return o instanceof Set && src.containsAll((Set) o);
}
@Override
public Set<E> get(int index) {
Set<E> result = new HashSet<>();
for (int i = 0; index != 0; i++, index >>=1) {
if((index & 1) == 1) {
result.add(src.get(i));
}
}
return result;
}
};
}
}
AbstractCollection์ ํ์ฉํ์ฌ Collection ๊ตฌํ์ฒด๋ฅผ ์์ฑํ ๋๋ Iterable์ฉ ๋ฉ์๋ ์ธ์ contains์ size๋ง ๋ ๊ตฌํํ๋ฉด ๋๋ค.
contains์ size๋ฅผ ๊ตฌํํ๋ ๊ฒ ๋ถ๊ฐ๋ฅํ๋ค๋ฉด ์ปฌ๋ ์
๋ณด๋ค๋ ์คํธ๋ฆผ์ด๋ Iterable์ ๋ฆฌํดํ๋ ํธ์ด ๋ซ๋ค(๋ณ๋์ ๋ฉ์๋๋ฅผ ๋ถ์ด ๋ ๋ฐฉ์ ๋ชจ๋ ์ ๊ณตํด๋ ๋๋ค).
๋ถ๋ถ ๋ฆฌ์คํธ๋ฅผ ๊ตฌํ๋ ๋ฐฉ๋ฒ
- (a, b, c)์ prefixes - (a), (a, b), (a, b, c)
- (a, b, c)์ suffixes - (c), (b, c), (a, b, c)
- ๋น ๋ฆฌ์คํธ(empty list)
public class SubList {
public static <E> Stream<List<E>> of(List<E> list) {
return Stream.concat(Stream.of(Collections.emptyList()), // ๋น ๋ฆฌ์คํธ
prefixes(list).flatMap(SubList::suffixes));
}
public static <E> Stream<List<E>> prefixes(List<E> list) {
return IntStream.rangeClosed(1, list.size())
.mapToObj(end -> list.subList(0, end));
}
public static <E> Stream<List<E>> suffixes(List<E> list) {
return IntStream.rangeClosed(0, list.size())
.mapToObj(start -> list.subList(start, list.size()));
}
}
public static <E> Stream<List<E>> of(List<E> list) {
return IntStream.range(0, list.size())
.mapToObj(start ->
IntStream.rangeClosed(start + 1, list.size())
.mapToObj(end -> list.subList(start, end)))
.flatMap(x -> x);
}
์คํธ๋ฆผ ๋ฆฌํด๋ง ์ ๊ณต๋๋ ๋ฐ๋ณต๋ฌธ ์ฌ์ฉ์ด ํ์ํ ๋์๋ Iterable๋ก ๋ณํํด์ฃผ๋ ์ด๋ํฐ๋ฅผ ์ด์ฉํด์ผ ํ๋ค. (์ฝ๋๊ฐ ์ด์์ ํด์ง๊ณ , ์๊ฐ ์ปดํจํฐ๋ก 2.3๋ฐฐ ๋ ๋๋ฆฌ๋ค.) (์ฑ ์๋ ์ ๋์จ) ์ง์ ๊ตฌํํ Collection์ด ์คํธ๋ฆผ๋ณด๋ค 1.4๋ฐฐ(์๊ฐ ์ปดํจํฐ) ๋นจ๋๋ค(์ฝ๋๋ ๋ ์ง์ ๋ถํด์ก๋ค).
- ์์ ์ํ์ค๋ฅผ ๋ฆฌํดํ๋ ๋ฉ์๋๋ฅผ ์์ฑํ ๋ ์คํธ๋ฆผ ์ฌ์ฉ์์ ๋ฐ๋ณต๋ฌธ ์ฌ์ฉ์๊ฐ ๋ชจ๋ ์์ ์ ์๊ธฐ์ ์์ชฝ์ ๋ง์กฑ์ํค๋ ค๊ณ ๋ ธ๋ ฅํ์
- ์ปฌ๋ ์
์ ๋ฆฌํดํ ์ ์๋ค๋ฉด ์ปฌ๋ ์
์ ์ด์ฉํ์
- ์์ ๊ฐ์๊ฐ ์ ๊ฑฐ๋ ์ด๋ฏธ ์ปฌ๋ ์ ์ ๋ด์ ๊ด๋ฆฌํ๊ณ ์์ผ๋ฉด ํ์ค ์ปฌ๋ ์ (E.g ArrayList)์ ์ด์ฉํ์
- ๊ทธ ์ธ์๋ ์ ์ฉ ์ปฌ๋ ์ (E.g ๋ฉฑ์งํฉ)์ ๊ตฌํํ๋ ๊ฒ์ ๊ณ ๋ คํ์
- ์ปฌ๋ ์ ์ ๋ฆฌํดํ ์ ์๋ค๋ฉด ์คํธ๋ฆผ์ด๋ Iterable ์ค ๋ ๋์ ๊ฒ์ ์ด์ฉํ์
- ๋ง์ฝ ๋์ค์ Stream ์ธํฐํ์ด์ค๊ฐ Iterable์ ์ง์ํ๋๋ก ์์ ๋๋ค๋ฉด, ์คํธ๋ฆผ ์ฒ๋ฆฌ์ ๋ฐ๋ณต์ ๋ชจ๋ ์ฌ์ฉ ๊ฐ๋ฅํ๋ ์์ฌํ๊ณ ์คํธ๋ฆผ์ ๋ฆฌํดํ๋ฉด ๋ ๊ฒ์ด๋ค.