λͺ©μ°¨
“컬λ μ μ λ°μ΄ν°λ₯Ό λ£μλλ°, μ΄λ»κ² κΊΌλ΄μΌ ν μ§ λͺ¨λ₯΄κ² μ΄μ.”
“forλ¬Έ μ°λ€ κ°μκΈ° μμΈκ° ν°μ‘λλ° μ΄μ λ₯Ό λͺ¨λ₯΄κ² μ΄μ.”
Javaλ₯Ό μ²μ λ°°μ°κ±°λ μ€λ¬΄μ λ€μ΄μ¨ μ΄λ³΄ κ°λ°μλ€μ΄ κ°μ₯ μμ£Ό νΌλμ€λ¬μνλ κ² μ€ νλκ° μ»¬λ μ μν λ°©μμ λλ€.
Iterator, for-each, ListIterator, forEach(), Stream APIκΉμ§… λλ체 λκ° λ€λ₯΄κ³ , μΈμ λ μ¨μΌ ν κΉμ?
μ΄λ² κΈμμλ μλ° μ»¬λ μ μνμ λͺ¨λ λ°©μμ μμ μ½λ μ€μ¬μΌλ‘ λΉκ΅νκ³ , μ€λ¬΄μμ μμ£Ό ν°μ§λ μμΈ μν©κΉμ§ μμλ³΄κ² μ΅λλ€.
β μ 컬λ μ μν λ°©μμ΄ μ΄λ κ² λ§μκΉ?
Javaλ κΎΈμ€ν λ°μ ν΄ μ€λ©΄μ κ°λ°μλ€μ μꡬμ κΈ°μ νλ¦μ λ§μΆ° λ€μν μν λ°©μμ λμ ν΄ μμ΅λλ€.
κ° λ°©μμ κ·Έ μμ μμ λΆνΈν¨μ ν΄μνκ±°λ μμ°μ±μ λμ΄κΈ° μν΄ λ±μ₯ν κ²μ΄μ£ .
λ²μ | κΈ°λ₯ | νΉμ§ |
Java 1.2 | Iterator | μμ ν μμ |
Java 5 | for-each | κ°κ²°ν λ¬Έλ² |
Java 8 | forEach(), Stream | ν¨μν νλ‘κ·Έλλ° μ€νμΌ |
β‘οΈ λͺ¨λ μ¬μ ν μ¬μ© κ°λ₯νλ©°, κ° λ°©μμ μν©μ λ§μΆ° μ νν΄μΌ μ΅μ μ μ½λ νμ§μ λΌ μ μμ΅λλ€.
πΉ Iterator
Iteratorλ 컬λ μ μ μμλ₯Ό μμ°¨μ μΌλ‘ νμν μ μλ νμ€ μΈν°νμ΄μ€μ λλ€.
νΉν μν μ€ μμλ₯Ό μμ νκ² μ κ±°ν μ μλ μ μΌν λ°©λ²μ λλ€.
List<String> items = new ArrayList<>(List.of("μ¬κ³Ό", "μν λ°λλ", "μ°μ "));
Iterator<String> iterator = items.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if (item.contains("μν")) {
iterator.remove(); // μμ ν μ κ±°!
}
}
π νΉμ§ λ° μ₯μ
- μμ μ κ±°μ μμ (ConcurrentModificationException λ°©μ§)
- λͺ¨λ Collectionμμ λμΌν λ°©μμΌλ‘ μ¬μ© κ°λ₯
- λ©λͺ¨λ¦¬ μ¬μ©λμ΄ ν¨μ¨μ (νΉν λμ©λ λ°μ΄ν° μν μ)
β οΈ λ¨μ
- μ½λκ° μ₯ν©ν¨
- remove()λ next() νΈμΆ μ΄νμλ§ μ¬μ© κ°λ₯
- List.of() κ°μ λΆλ³ 컬λ μ μμλ μμΈ λ°μ
π οΈ μΈμ μ¬μ©ν κΉ?
- μν μ€ μμλ₯Ό μ κ±°ν΄μΌ ν λ
- μΈλΆ APIμμ λ°μ 컬λ μ μ΄ λΆνμ€ν λ
- λ©λͺ¨λ¦¬ λ―Όκ°ν νκ²½μμ λλ λ°μ΄ν° μ²λ¦¬ μ
π for-each
for-eachλ Java 5λΆν° λμ λ ν₯μλ forλ¬Έμ λλ€.
μ½λκ° κ°κ²°νκ³ κ°λ μ±μ΄ μ’μ, λλΆλΆμ μν μμ μμ μ¬μ©λ©λλ€
List<String> fruits = List.of("μ¬κ³Ό", "λ°°", "ν¬λ");
for (String fruit : fruits) {
System.out.println(fruit);
}
π νΉμ§ λ° μ₯μ
- κ°μ₯ μ§κ΄μ μΈ μν λ¬Έλ²
- κ°λ μ±μ΄ λ°μ΄λ νμ μ½λμ μ 리
- λ°°μ΄, List, Set, Map λ± λͺ¨λ 컬λ μ μ μ μ© κ°λ₯
- μΈλ±μ€ μ κ²½ μΈ νμ μμ
β οΈ λ¨μ
- μΈλ±μ€ μ κ·Ό λΆκ°
- μμ μ κ±° μ ConcurrentModificationException λ°μ
for (String item : list) {
if (item.equals("B")) {
list.remove(item); // β μμΈ λ°μ
}
}
π οΈ μΈμ μ¬μ©ν κΉ?
- λ¨μνκ² λͺ¨λ μμλ₯Ό μ²λ¦¬ν λ
- κ°λ μ±μ΄ μ€μν νλ‘μ νΈμμ
- μμ μμ κ° νμ μλ κ²½μ°
πΈ μ ν΅μ μΈ forλ¬Έ
μ΅μν for (int i = 0; i <...; i++) λ°©μμΌλ‘, μΈλ±μ€λ₯Ό κΈ°λ°μΌλ‘ μΈλ°ν μ μ΄κ° νμν κ²½μ° μ μ©ν©λλ€.
List<String> songs = Arrays.asList("λ
Έλ1", "λ
Έλ2", "λ
Έλ3");
for (int i = 0; i < songs.size(); i++) {
System.out.println(i + 1 + "λ²μ§Έ: " + songs.get(i));
}
π νΉμ§ λ° μ₯μ
- μΈλ±μ€ νμ© κ°λ₯ (μμ νμν λ κ°λ ₯)
- μμ μν, 건λλ°κΈ° λ± μμ λ‘μ΄ νλ¦
β οΈ λ¨μ
- LinkedListμμλ μ±λ₯ μ ν κ°λ₯ (get(i)κ° O(n))
LinkedList<String> list = new LinkedList<>();
for (int i = 0; i < list.size(); i++) {
list.get(i); // λ§€λ² μ²μλΆν° νμ!
}
π οΈ μΈμ μ¬μ©ν κΉ?
- μΈλ±μ€ κΈ°λ° μ κ·Όμ΄ νμν κ²½μ°
- ArrayListμ κ°μ λλ€ μ κ·Ό 컬λ μ μμ
- νΉμ ν¨ν΄(μ§μ μΈλ±μ€λ§, μμ λ±)μ΄ νμν κ²½μ°
π forEach λ©μλ
Java 8λΆν° μΆκ°λ forEach λ©μλλ λλ€ ννμκ³Ό ν¨κ» μ¬μ©λλ©°, κ°λ¨ν λ‘μ§μ λΉ λ₯΄κ² μ μ©ν λ μ μ©ν©λλ€.
List<Product> products = getProductList();
products.forEach(product -> {
if (product.isOnSale()) {
product.applyDiscount(0.2);
}
});
π νΉμ§ λ° μ₯μ
- λλ€μκ³Ό μμ°μ€λ½κ² κ²°ν©
- Map.forEach((key, value) -> {}) λ±μλ νμ© κ°λ₯
β οΈ λ¨μ
- break, continue λΆκ°λ₯
- μμΈ μ²λ¦¬ μ try-catch νμ
π οΈ μΈμ μ¬μ©νλ?
- κ°λ¨ν μν + μΆλ ₯/μ²λ¦¬
- λλ€μ κΈ°λ°μ ν¨μν μ€νμΌλ‘ μμ±ν λ
π Stream API νμ©
Streamμ 컬λ μ λ°μ΄ν°λ₯Ό ν¨μν μ€νμΌλ‘ μ²λ¦¬ν μ μκ² ν΄μ£Όλ APIμ λλ€.
νν°λ§, λ³ν, μ§κ³, λ³λ ¬ μ²λ¦¬ λ± λ³΅μ‘ν μμ μ μ ν©ν©λλ€.
double avg = students.stream()
.filter(s -> s.getMajor().equals("CS"))
.mapToDouble(Student::getGpa)
.average()
.orElse(0.0);
π νΉμ§ λ° μ₯μ
- μ μΈν μ²λ¦¬ → κ°λ μ± λμ
- parallelStream()μΌλ‘ λ³λ ¬ μ²λ¦¬ μ§μ
- filter, map, reduce λ± μ°μ° κ°λ₯
β οΈ λ¨μ
- break/continue μ¬μ© λΆκ°
- νμ΅ κ³‘μ μ‘΄μ¬
- κ³Όλνκ² μ°λ©΄ μ€νλ € 볡μ‘ν΄μ§
π οΈ μΈμ μ¬μ©ν κΉ?
- λ°μ΄ν°λ₯Ό νν°λ§, κ°κ³΅, μ§κ³ν λ
- λ³λ ¬ μ²λ¦¬λ‘ μλ ν₯μμ΄ νμν κ²½μ°
- μ½λμ μ μΈμ±κ³Ό κ°λ μ±μ λμ΄κ³ μΆμ λ
β οΈ μμ£Ό λ§λλ μμΈ: ConcurrentModificationException
ConcurrentModificationExceptionμ 컬λ μ μ μν μ€μΌ λ, κ·Έ 컬λ μ μ ꡬ쑰λ₯Ό λμμ μμ νλ©΄ λ°μνλ λ°νμ μμΈμ λλ€.
μ¦, λ€μκ³Ό κ°μ μν©μμ λ°μν©λλ€:
- for-each λλ Iteratorλ₯Ό ν΅ν΄ μν μ€μΌ λ
- remove(), add() λ±μΌλ‘ μμλ₯Ό μ§μ λ³κ²½ν κ²½μ°
List<String> names = new ArrayList<>(List.of("Tom", "Jane", "Mike"));
for (String name : names) {
if (name.startsWith("J")) {
names.remove(name); // β μμΈ λ°μ
}
}
β οΈ μ λ°μν κΉ?
μλ°μ λλΆλΆμ 컬λ μ ν΄λμ€λ λ΄λΆμ μΌλ‘ “ꡬ쑰 λ³κ²½ μ fail-fast” λ©μ»€λμ¦μ μ μ©νκ³ μμ΅λλ€.
μ¦, μν λμ€ μ»¬λ μ μ ν¬κΈ°λ κ΅¬μ‘°κ° λ³κ²½λλ©΄ μ¦μ μμΈλ₯Ό λμ Έ λ²κ·Έλ₯Ό μ‘°κΈ°μ κ°μ§νκ² ν΄ μ€λλ€.
λΉ λ₯΄κ² μ€ν¨(fail-fast)ν¨μΌλ‘μ¨, μν κ²°κ³Όμ λΆμΌμΉλ λ²κ·Έλ₯Ό λ°©μ§νλ λ©μ»€λμ¦μ λλ€.
β μμ νκ² μ κ±°νλ 4κ°μ§ λ°©λ²
1οΈβ£ Iterator.remove() μ¬μ©
Iteratorλ₯Ό μ¬μ©ν κ²½μ°, next()λ‘ κΊΌλΈ μμμ λν΄ remove() λ©μλλ₯Ό μ΄μ©ν΄ μμ νκ² μμ ν μ μμ΅λλ€.
List<Integer> numbers = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6));
Iterator<Integer> it = numbers.iterator();
while (it.hasNext()) {
Integer num = it.next();
if (num % 2 == 0) {
it.remove(); // μμ νκ² μ κ±°
}
}
System.out.println(numbers); // [1, 3, 5]
π‘ λ°λμ next()λ₯Ό νΈμΆν νμ remove()λ₯Ό μ¨μΌ ν©λλ€.
2οΈβ£ removeIf() (Java 8 μ΄μ)
컬λ μ μ removeIf(Predicate) λ©μλλ₯Ό μ΄μ©νλ©΄ λλ€μ κΈ°λ°μΌλ‘ 쑰건μ λ§μ‘±νλ μμλ§ μ κ±°ν μ μμ΅λλ€.
List<String> words = new ArrayList<>(List.of("apple", "banana", "avocado", "berry"));
words.removeIf(word -> word.startsWith("a"));
System.out.println(words); // [banana, berry]
κ°κ²°νκ³ μ€λ¬΄μμ μμ£Ό μ°μ λλ€.
3οΈβ£ μλ°©ν₯ forλ¬Έ μ¬μ©
μμμλΆν° μννλ©΄μ μμ νλ©΄ μΈλ±μ€κ° λ°λ €μ μ€λ₯κ° λ°μν μ μμΌλ―λ‘, λ€μμλΆν° κ±°κΎΈλ‘ μννλ©΄μ μ κ±°ν©λλ€.
List<String> items = new ArrayList<>(List.of("A", "B", "C", "B", "D"));
for (int i = items.size() - 1; i >= 0; i--) {
if (items.get(i).equals("B")) {
items.remove(i);
}
}
System.out.println(items); // [A, C, D]
νΉν μΈλ±μ€ κΈ°λ° μμ κ° νμν κ²½μ° ν¨κ³Όμ μ λλ€.
4οΈβ£ Stream.filter()λ‘ μ 컬λ μ μμ±
μλ³Έ 컬λ μ μ λ³κ²½νμ§ μκ³ , 쑰건μ λ§μ‘±νλ μμλ§ λ¨κΈ΄ μλ‘μ΄ λ¦¬μ€νΈλ₯Ό μμ±ν©λλ€.
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6);
List<Integer> oddNumbers = numbers.stream()
.filter(n -> n % 2 != 0)
.collect(Collectors.toList());
System.out.println(oddNumbers); // [1, 3, 5]
μλ³Έμ μ μ§ν΄μΌ νκ±°λ λΆλ³ 컬λ μ (List.of λ±)μ λ€λ£° λ μ μ©ν©λλ€.
π Tip
- for-eachλ stream() μμμλ μ λ remove() νμ§ λ§ κ²
- 쑰건μ λ°λΌ μμ κ° νμνλ©΄ → removeIf() / Iterator.remove() / μλ°©ν₯ for
- λΆλ³ 리μ€νΈμΈ κ²½μ° → μλ‘μ΄ μ»¬λ μ μΌλ‘ Stream.filter()λ‘ μ¬μμ±
π μν©λ³ μΆμ² κ°μ΄λ
μν© | μΆμ² λ°©μ | μ΄μ |
μμ μ κ±° | Iterator, removeIf() | μμ νκ² μ κ±° κ°λ₯ |
λ¨μ μν | for-each | μ§κ΄μ , κ°λ μ± μ°μ |
μΈλ±μ€ κΈ°λ° μ κ·Ό | forλ¬Έ | 컀μ€ν°λ§μ΄μ§ μ©μ΄ |
λ°μ΄ν° κ°κ³΅ | Stream | μ μ°νκ³ μ μΈμ μ²λ¦¬ κ°λ₯ |
λ³λ ¬ μ²λ¦¬ | parallelStream | CPU νμ© κ·Ήλν |
λλ€ μ€νμΌ | forEach() | κ°κ²°ν νν |
π λ§λ¬΄λ¦¬
“컬λ μ μ κΊΌλ΄ μ°λ λ²μ μλ©΄, μ½λμ νμ§μ΄ λ¬λΌμ§λ€.”
μλ°μ 컬λ μ μν λ°©μμ λ¨μν λ¬Έλ² μ°¨μ΄κ° μλλΌ, μ±λ₯κ³Ό μμ μ±, μ½λ κ°λ μ±μ μ§κ²°λλ μ€μν μ νμ λλ€.
- λ¨μ μνμλ for-each
- μΈλ±μ€κ° νμν λ μ ν΅μ μΈ for
- μμ μμ κ° νμνλ€λ©΄ Iterator λλ removeIf
- μ μΈν μ€νμΌμ΄λ λ³λ ¬ μ²λ¦¬μλ Stream
κ° λ°©μμ΄ λμ λ μ΄μ μ μ°μμλ₯Ό μ΄ν΄νλ©΄ λΆνμν μμΈλ₯Ό λ°©μ§νκ³ , λ μμ μ μΈ μ½λλ₯Ό μμ±ν μ μμ΅λλ€.
λ€μ κΈμμλ μ λ€λ¦κ³Ό μμΌλμΉ΄λλ‘ νμ μμ μ± λμ΄λ λ°©λ²μ λν΄ λ€λ€λ³΄κ² μ΅λλ€.
κΆκΈν μ μ΄ μλ€λ©΄ μΈμ λ λκΈλ‘ λ¨κ²¨μ£ΌμΈμ π