์๋ฐ์์ ์ปฌ๋ ์ ์ ๋ฐ๋ณตํ๋ ์ต์ ์๋ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์๋ค. ์ด๋ฒ ๊ธ์์๋ 2๊ฐ์ง ๋น์ทํ ์ ๊ทผ ๋ฐฉ์์ ์ดํด๋ณธ๋ค.
๋๋ถ๋ถ ๋๋ค ๋์ผํ ๊ฒฝ๊ณผ๋ฅผ ๋ณด์ด์ง๋ง, ๋ช ๊ฐ์ง ๋ฏธ๋ฌํ ์ฐจ์ด์ ์ ๋ณผ ์์ ์ด๋ค.
a. ๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ ํฅ์ for๋ฌธ์ ์ด์ฉํ๋ ๊ฒ์ด๋ค.
for(String s : list) {
// do something with s
}
b. ๋๋ค์์ผ๋ก๋ ๊ฐ๋ฅํ๋ค(Funtional-style)
Consumer<String> consumer = s -> { System.out::println };
list.forEach(consumer);
c. stream์ forEach()๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
list.stream().forEach(consumer);
์๋ง ์ฌ๊ธฐ์ ์ฐจ์ด๊ฐ ๋๋ ๊ฒ ๊ฐ๋ค.
- Collection.foreach()์ ๊ฒฝ์ฐ ์์์ ๋ํ ์ฒ๋ฆฌ ์์๋ฅผ ์ง์ ์ ์ํ๋ค.
- ๋ฐ๋ฉด Collection.stream().foreach()์ ๊ฒฝ์ฐ ์ฒ๋ฆฌ ์์๋ฅผ ์ ์๋์ง ์๋๋ค. ์์ ๊ฒฝ์ฐ ๋ ๊ฐ์ง๋ ํฌ๊ฒ ์ฐจ์ด๊ฐ ๋์ง ์๋๋ค.
๋ณ๋ ฌ ์คํธ๋ฆผ์ ์ฌ์ฉํ๋ฉด ์ฌ๋ฌ ์ค๋ ๋(multi thread)์์ ์คํธ๋ฆผ์ ์คํํ ์ ์์ผ๋ฉฐ ์ด๋ฐ ์ํฉ์์๋ ์คํ ์์๋ ์ ์๋์ง ์๋๋ค. java๋ Collectors.toList()์ ๊ฐ์ ํฐ๋ฏธ๋ ์์ ์ด ํธ์ถ๋๊ธฐ ์ ์ ๋ชจ๋ ์ค๋ ๋๊ฐ ์๋ฃ๋๋๋ก ์๊ตฌํ๋ค.
์ฌ๊ธฐ์ ๋งํ๋ ํฐ๋ฏธ๋ ์์
์ ์คํธ๋ฆผ์ ์ฒ๋ฆฌ๋ฅผ ๋๋ด๊ณ ๊ฒฐ๊ณผ๋ฅผ ์์ฑํ๋ ์์
์ ๋งํ๋ค. ์ฆ ์คํธ๋ฆผ์ ์๋นํ๊ณ , ์คํธ๋ฆผ์ ๋ํ ๋ ์ด์์ ์์
์ ํ์ฉํ์ง ์๋๋ค.
ex) list.forEach(System.out::println), list.stream().collect(Collectors.toList()), list.stream().reduce(~) ๋ฑ๋ฑ
์๋ ์ฝ๋๋ฅผ ์คํํด๋ณด์
list.forEach(System.out::print);
System.out.print(" ");
list.parallelStream().forEach(System.out::print);
์ฝ๋๋ฅผ ์ฌ๋ฌ ๋ฒ ์คํํ๋ฉด list.forEach()๊ฐ ์ฝ์
์์๋๋ก ํญ๋ชฉ์ ์ฒ๋ฆฌํ๋ค. ๋ฐ๋ฉด list.parallelStream().forEach()๋ ์คํ๋ ๋๋ง๋ค ๋ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค
์คํ ๊ฒฐ๊ณผ 
๊ฐ๋จํ๊ฒ ์ญ์์ผ๋ก ๋ฐ๋ณตํ๋ Iterator๋ฅผ ์ ์ํด์ ์คํ์์ผ ๋ณด์.
class ReverseList extends ArrayList<String> {
@Override
public Iterator<String> iterator() {
int startIndex = this.size() - 1;
List<String> list = this;
Iterator<String> it = new Iterator<String>() {
private int currentIndex = startIndex;
@Override
public boolean hasNext() {
return currentIndex >= 0;
}
@Override
public String next() {
String next = list.get(currentIndex);
currentIndex--;
return next;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
return it;
}
}
๊ทผ๋ฐ Bealdung์์ Collection.forEach()์์ ๋ด๋ถ์ ์ผ๋ก custom iterator๋ฅผ ์ฌ์ฉํ๋ ๊ฒ ์ฒ๋ผ ๋์์๊ณ
์๋ฌธ์๋ ์๋์ฒ๋ผ ๋์์๋๋ฐ ์ง์ ๋๋ ค๋ณธ ๊ฒฐ๊ณผ ์๋์๋ค.
List<String> myList = new ReverseList();
myList.addAll(list);
myList.forEach(System.out::print);
System.out.print(" ");
myList.stream().forEach(System.out::print);
์์ ๊ฒฐ๊ณผ 
์ค์ ๊ฒฐ๊ณผ 
์ปดํ์ผ๋ ์ฝ๋๋ ๋ณด๋ฉด iterator๋ฅผ ํธ์ถํ๊ณ ์์ง ์๊ณ Collection.forEach()์ ์ ์ํ Consumer ๋ก์ง๋๋ก ์ถ๋ ฅ ํ๋ค. 
์ค์ ๋ก ๋ฐ๋๋ก ์ถ๋ ฅํ๊ณ ์ถ์ผ๋ฉด, ์๋์ฒ๋ผ
- custom iterator๋ฅผ ์ง์ ์ฌ์ฉํ๊ฑฐ๋ - enhanced for-loop๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค. (๋ด๋ถ์ ์ผ๋ก ๊ตฌํํ iterator๋ฅผ ์ฌ์ฉ)
List<String> myList = new ReverseList();
myList.addAll(list);
Iterator iterator = myList.iterator();
System.out.println("custom iterator ์ง์ ์ฌ์ฉ");
while(iterator.hasNext()) {
System.out.print(iterator.next());
}
System.out.println();
// ๊ตฌํํ iterator๋ฅผ ํธ์ถํด์ ์ฌ์ฉํ๊ณ ์์
System.out.println("enhanced for-loop");
for(String s : myList) {
System.out.print(s);
}
System.out.println();
// ์ฐพ์๋ค ๋ฒ์ธ, ์ปดํ์ผ๋ฌ๊ฐ forEach๋ฅผ ์ปดํ์ผ ํ ๋ iterable๋ก ์ฌ์ฉํ๋๊ฒ ์๋๋ผ
// ๊ทธ๋ฅ list์ foreach๋ฌธ์ ํธ์ถํ๊ณ ์์
// foreachํจ์๋ฅผ ๋ณด๋ฉด ์์์ ํฅ์for๋ฌธ์ ์ฌ์ฉํ๊ณ ์๋๋ฐ ํ๋ผ๋ฏธํฐ๋ก ๋๊ธด Consumer ํด๋์ค(Functional ํด๋์ค) ๋๋ก ๋์
System.out.println("๊ทธ๋ฅ forEach() ์ฌ์ฉ");
myList.forEach(x -> System.out.print(x));
System.out.println();
//stream์ foreach ํธ์ถ
System.out.println("์คํธ๋ฆผ forEach() ์ฌ์ฉ");
myList.stream().forEach(System.out::print);
์คํ ๊ฒฐ๊ณผ 
์ ์ฒด ์ปดํ์ผ ์ฝ๋
public class JavaCollectionStreamForeach {
public JavaCollectionStreamForeach() {
}
public static void main(String[] args) {
List<String> list = Arrays.asList("A", "B", "C", "D");
List<String> myList = new ReverseList();
myList.addAll(list);
Iterator iterator = myList.iterator();
System.out.println("custom iterator ์ง์ ์ฌ์ฉ");
while(iterator.hasNext()) {
System.out.print(iterator.next());
}
System.out.println();
System.out.println("enhanced for-loop");
Iterator var4 = myList.iterator();
while(var4.hasNext()) {
String s = (String)var4.next();
System.out.print(s);
}
System.out.println();
System.out.println("๊ทธ๋ฅ forEach() ์ฌ์ฉ");
myList.forEach((x) -> {
System.out.print(x);
});
System.out.println();
System.out.println("์คํธ๋ฆผ forEach() ์ฌ์ฉ");
Stream var10000 = myList.stream();
PrintStream var10001 = System.out;
Objects.requireNonNull(var10001);
var10000.forEach(var10001::print);
}
}
๊ทธ๋ฌ๋ฉด์ `The reason for the different results is that forEach() used directly on the list uses the custom iterator` ๋ผ๊ณ ๋์ด์๋๋ฐ iterator๊ฐ ์๋๋ผ ์ ์ํ Functional-class ๋๋ก ์ถ๋ ฅ๋๋ค.
๋๋ถ๋ถ์ ์ปฌ๋ ์
์ ๋ฐ๋ณต(iterating)ํ๋ ๋์์๋ ๊ตฌ์กฐ์ ์ผ๋ก ์์ ํ๋ฉด ์๋๋ค.
๋ง์ฝ, ๋ฐ๋ณตํ๋ ๋์ ์์๊ฐ ์ญ์ ๋๊ฑฐ๋ ์ถ๊ฐ๋๋ฉด ConcurrentModification exception ์ด ๋ฐ์ํ๋ค.
๊ฒ๋ค๊ฐ ์ปฌ๋ ์
์ ๋น ๋ฅด๊ฒ ์คํจ(fast fail)๋๋๋ก ์ค๊ณ ๋์ด์๋ค. ์ฆ, ์์ ์ด ๋ฐ์ํ๋ฉด ์ฆ์ ์์ธ๊ฐ ๋ฐ์ํ๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ ์คํ ์ค์ ์์๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ ์ ๊ฑฐํ๋ฉด ConcurrentModification ์์ธ๊ฐ ๋ฐ์ํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋์ค์ ์์ธ๊ฐ ๋ฐ์ํฉ๋๋ค.
"D"๋ฅผ ์ญ์ ํ๋ Consumer ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ณ
Consumer<String> removeElement = s -> {
System.out.println(s + " " + list.size());
if (s != null && s.equals("A")) {
list.remove("D");
}
};
- remove() ๋ฉ์๋๋ AbstractCollection์ remove() ๋ฉ์๋๋ฅผ ํธ์ถ
- ๋ด๋ถ์์ iterator๋ฅผ ํตํด iterator์ remove๋ฅผ ์ ํธ์ถํ๋ค.
iterator ์ธํฐํ์ด์ค์ ์ ์ ๋์ด์๋ remove()๋ฉ์๋๋ฅผ ๋ณด๋ฉด ํญ์ `UnsupportedOperationException` ์์ธ๋ฅผ ๋์ง๊ฒ ๋์ด์๋ค. 
์คํ๊ฒฐ๊ณผ 
#### forEach() ๋ฉ์๋๋ ์คํจ๊ฐ ๋นจ๋ผ์, ๋ฐ๋ณต์ ์ค์งํ๊ณ ๋ค์ ์์๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ ์ ์์ธ๋ฅผ ํ์ธํ๋ค.
์ง๊ธ๋ถํฐ๋ stream().forEach()๋ฅผ ์ดํด๋ณด์
list.stream().forEach(removeElement);
๊ต์ฌ์์๋ ๋๋ ค๋ณด๋ฉด ์๋ ๊ฒฐ๊ณผ์ฒ๋ผ ๋์จ๋ค๊ณ ํ๋ค
๊ทผ๋ฐ ์ค์ ๋ก ๋๋ ค๋ณด๋ฉด ์๋์ฒ๋ผ๋์จ๋ค...
#### stream()์ forEach()๋ Collection.forEach()์ ๋ค๋ฅด๊ฒ ๋ชจ๋ ์์๋ฅผ ํ์ธํ๊ณ ์์ธ๋ฅผ ์ถ๋ ฅํ๋ค๋๊ฑธ ๋ณด์ฌ์ฃผ๊ณ ์ถ์ ๊ฒ ๊ฐ๋ค.
์ค๊ฐ์ ๊ฐ์ ๋ฐ๊พธ๋ ์ฝ๋๋ฅผ ์คํํด๋ณด๋ฉด
list.forEach(e -> {
list.set(1, "E");
});
list.forEach(System.out::print);
์คํ๊ฒฐ๊ณผ
์ ์์
์ ์ํํ๋๋ฐ ๋ฌธ์ ๊ฐ ์๋ค?!?!
๋ฌธ์ ๊ฐ ์์ง๋ง Java์์๋ ์คํธ๋ฆผ์ ๋ํ ์์
์ด ๊ฐ์ญํ์ง ์์์ผ ํฉ๋๋ค.
์ด๋ ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ ์คํ ์ค์ ์์๋ฅผ ์์ ํด์๋ ์ ๋๋ค๋ ์๋ฏธ์
๋๋ค
๊ทธ ์ด์ ๋ ์คํธ๋ฆผ์ด ๋ณ๋ ฌ ์คํ์ ์ฉ์ดํ๊ฒ ํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ฌ๊ธฐ์ ์คํธ๋ฆผ ์์๋ฅผ ์์ ํ๋ฉด ์๊ธฐ์น ์์ ๋์์ด ๋ฐ์ํ ์ ์์ต๋๋ค.
์ปฌ๋ ์ ์ ๋ฐ๋ณตํ๋ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ๋ง ๋น๊ตํ๊ธฐ ์ํ ๊ฒ์ด๋ผ๋ ์ ์ ์ ์ํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ํ์๋ ๋์์ ๋ฐ๋ผ ์ ํ์ฑ์ด ๊ฒฐ์ ๋๋ ์ฝ๋๋ฅผ ์์ฑํด์๋ ์ ๋ฉ๋๋ค.
์คํธ๋ฆผ์ ํ์ํ์ง ์์ง๋ง ์ปฌ๋ ์ ์ ๋ํด์๋ง ๋ฐ๋ณตํ๋ ค๋ ๊ฒฝ์ฐ ์ฒซ ๋ฒ์งธ ์ ํ์ ์ปฌ๋ ์ ์์ ์ง์ forEach()๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค.
'๊ฐ์ธ ๊ณต๋ถ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[๋ฐฑ์ค] ์ด์น์ (1) | 2024.11.23 |
---|---|
[TIL] ํ๋ก์ ๋ํด์ ๊ฐ๋จํ ์ ๋ฆฌ (1) | 2024.11.22 |
๋ฐฑ์คํ๋ธ ์ฐ๋ํ๊ธฐ (0) | 2023.06.15 |
๋งฅ๋ถ ์ํคํ ์ฒ ARM๊ธฐ๋ฐ์ธ์ง Intel๊ธฐ๋ฐ์ธ์ง ํ์ธํ๊ธฐ (0) | 2023.05.11 |