Iterator
Iterator ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ์ฌ Java ์ปฌ๋ ์
๋ฐ์ดํฐ๋ฅผ ์ํํ๊ณ ์ ๊ทผํ ์ ์๋ค.
Iterator๋ ์ปฌ๋ ์
๋ด์ ์์๋ฅผ ๋ฐ๋ณต์ ์ผ๋ก ์ํํ๋ฉด์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ์ ์๋ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํ๊ณ , ์ปฌ๋ ์
์ ๋ด๋ถ ๊ตฌ์กฐ๋ฅผ ์ ํ์ ์์ด ๋ฐ์ดํฐ์ ์ ๊ทผํ ์ ์๋๋ก ํด์ค๋ค.
Iterator ์ธํฐํ์ด์ค์ ์ฃผ์ ๋ฉ์๋
Iterator ์ธํฐํ์ด์ค๋ ๋ค์๊ณผ ๊ฐ์ ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
boolean hasNext()
: ๋ค์ ์์๊ฐ ์กด์ฌํ๋์ง ํ์ธํ๋ ๋ฉ์๋๋ก, ๋ค์ ์์๊ฐ ์์ผ๋ฉด true
๋ฅผ ๋ฐํํ๊ณ , ๋ ์ด์ ์ํํ ์์๊ฐ ์์ผ๋ฉด false
๋ฅผ ๋ฐํ
E next()
: ๋ค์ ์์๋ฅผ ๋ฐํ(ํธ์ถํ ๋ค์ ์์๊ฐ ์์ ๊ฒฝ์ฐ NoSuchElementException
์์ธ๊ฐ ๋ฐ์)
public class IteratorExample {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
names.add("Charlie");
// Iterator ์์ฑ
Iterator<String> iterator = names.iterator();
// ์ํํ๋ฉด์ ์ถ๋ ฅ
while (iterator.hasNext()) {
String name = iterator.next();
System.out.println(name);
}
}
}
์คํธ๋ฆผ
๋ฐ์ดํฐ ์์ค๋ฅผ ์ถ์ํํ๊ณ , ๋ค๋ฃจ๋๋ฐ ์์ฃผ ์ฌ์ฉ๋๋ ๋ฉ์๋๋ฅผ ์ ์ํ ์ธํฐํ์ด์ค
Java 8 ์ดํ์๋ ์คํธ๋ฆผ(Stream) API๊ฐ ๋์
๋์ด ์ปฌ๋ ์
๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ ๊ฐ๊ฒฐํ๊ณ ํํ๋ ฅ ์๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ๋ค.
์ปฌ๋ ์
์์๋ฅผ ๋๋ค์์ ํ์ฉํ์ฌ ์ฒ๋ฆฌํ ์ ์์ผ๋ฉฐ, Iterator๋ณด๋ค ๋ง์ ์ฐ์ฐ์ ์ง์
์คํธ๋ฆผ์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ ์์ค๊ฐ ๋ฌด์์ด๋ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋ค๋ฃฐ ์ ์๋๋ก ํด์ฃผ์ด ์ฝ๋์ ์ฌ์ฌ์ฉ์ฑ ํฅ์
class Example {
public static void main(String[] args) {
String[] array = {"a", "b", "c", "d", "e"};
List<String> list = Arrays.asList(array);
// ์ ๋ ฌ๋ ๋์ ์ถ๋ ฅ
Arrays.sort(array);
for (String string : array) {
System.out.println(string);
}
Collections.sort(list);
for (String string : list) {
System.out.println(string);
}
// ์คํธ๋ฆผ ์์ฑ
Stream<String> arrayStream = Arrays.stream(array);
String<String> listStream = list.stream();
// ์ ๋ ฌ๋ ๋์ ์ถ๋ ฅ
arrayStream.sorted().forEach(System.out::println);
listStream.sorted().forEach(System.out::println);
}
}
๋ ๊ฐ์ Stream ๋ฐ์ดํฐ ์์ค๋ ๋ค๋ฅด์ง๋ง, ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ ๋ ฌํ๊ณ ์ถ๋ ฅํ ์ ์๊ณ , ๋ํ ๋ฐ์ดํฐ ์์ค๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ ๋ ์ ๋ ฌ๋ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์๊ฒ ๋๋ค.
์คํธ๋ฆผ์ ํน์ง
1. ๋ฐ์ดํฐ ์์ค ๋ถ๋ณ
์คํธ๋ฆผ์ ๋ฐ์ดํฐ ์์ค๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ ์๋ก์ด ๋ฐ์ดํฐ ์์ค๋ฅผ ์์ฑํ๋ค.
class Example {
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "c", "d", "b", "e");
List<String> sortedList = list
.stream()
.sorted()
.collect(Collectors.toList()); // list๋ ๋ณ๊ฒฝ๋์ง ์์
}
}
2. ๋ด๋ถ ๋ฐ๋ณต
์คํธ๋ฆผ์ ์ฌ์ฉํ๋ฉด ๋ฐ๋ณต๋ฌธ์ ๋ฉ์๋์ ๋ด๋ถ์ ์จ๊ธธ ์ ์์ด ์ฝ๋๊ฐ ๊ฐ๊ฒฐํด ์ง๋ค.
class Example {
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c", "d", "e");
// ์ธ๋ถ ๋ฐ๋ณต
for (String string : list) {
System.out.println(string);
}
// ๋ด๋ถ ๋ฐ๋ณต
list.stream().forEach(System.out::println);
}
}
3. ์ค๊ฐ ์ฐ์ฐ๊ณผ ์ต์ข
์ฐ์ฐ
์ค๊ฐ ์ฐ์ฐ: ์คํธ๋ฆผ์ ๋ฐํํ๋ ์ฐ์ฐ์ผ๋ก, ์คํธ๋ฆผ์ ์ฐ์ํด์ ์ฌ๋ฌ ๊ฐ์ ์ค๊ฐ ์ฐ์ฐ์ ํธ์ถํ ์ ์๋ค.
์ต์ข
์ฐ์ฐ: ์คํธ๋ฆผ์ ๋ฐํํ์ง ์๋ ์ฐ์ฐ์ผ๋ก, ์คํธ๋ฆผ์ ์ต์ข
์ฐ์ฐ์ ํธ์ถํ๋ฉด ์คํธ๋ฆผ์ ์๋ชจํ๊ฒ ๋๋ค.
class Example {
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c", "d", "e");
Stream<String> stream = list.stream();
stream.sorted(); // ์ค๊ฐ ์ฐ์ฐ
stream.forEach(System.out::println); // ์ต์ข
์ฐ์ฐ
}
}
4. ์ผํ์ฑ
์ต์ข
์ฐ์ฐ์ ํธ์ถํ๋ฉด ์คํธ๋ฆผ์ ์๋ชจํ๊ฒ ๋๋ฉฐ, ์ดํ์๋ ์คํธ๋ฆผ์ ๋ค์ ์ฌ์ฉํ ์ ์๋ค.
์ฌ๊ธฐ์ ๋ฐ์ดํฐ ์์ค๋ ๋ถ๋ณ์ฑ ํน์ง์ ๊ฐ์ง๊ธฐ ๋๋ฌธ์, ์์ค๋ ๋ณ๊ฒฝ๋๊ฑฐ๋ ์ฌ๋ผ์ง์ง ์๋๋ค.
class Example {
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c", "d", "e");
Stream<String> stream = list.stream();
stream.sorted().forEach(System.out::println);
stream.sorted().forEach(System.out::println); // IllegalStateException
}
}
5. ์ง์ฐ ์ฐ์ฐ
์คํธ๋ฆผ์ ์ต์ข
์ฐ์ฐ์ด ํธ์ถ๋๊ธฐ ์ ๊น์ง๋ ์ค๊ฐ ์ฐ์ฐ์ด ์ค์ ๋ก ์ํ๋์ง ์๋๋ค.
์คํธ๋ฆผ ์์ฑ
๋๋ถ๋ถ์ ๋ฐ์ดํฐ ์์ค๋ ์คํธ๋ฆผ์ผ๋ก ๋ณํํ ์ ์๋ค.
Collection
์ธํฐํ์ด์ค: stream()
๋ฉ์๋๊ฐ ์ ์๋์ด ์์ด ์ปฌ๋ ์
์ ์คํธ๋ฆผ์ผ๋ก ๋ณํ(์์ ํด๋์ค ๋ชจ๋ ์ฌ์ฉ ๊ฐ๋ฅ)
Arrays
ํด๋์ค: ๋ฐฐ์ด์ ์คํธ๋ฆผ์ผ๋ก ๋ณํํ๋ stream()
๋ฉ์๋๊ฐ ์ ์๋์ด ์์ด ๋ฐฐ์ด์ ์คํธ๋ฆผ์ผ๋ก ๋ณํ
Map
์ธํฐํ์ด์ค: keySet()
, values()
, entrySet()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์คํธ๋ฆผ์ผ๋ก ๋ณํ
class Example {
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c", "d", "e");
Stream<String> stream1 = list.stream();
String[] array = {"a", "b", "c", "d", "e"};
Stream<String> stream2 = Arrays.stream(array);
Map<String, Integer> map = new HashMap<>() {{
put("a", 1);
put("b", 2);
put("c", 3);
}};
Stream<Map.Entry<String, Integer>> streamEntry = map.entrySet().stream();
Stream<String> streamKey = map.keySet().stream();
Stream<Integer> streamValue = map.values().stream();
}
}
๊ทธ ์ธ์ ์๋์ ๊ฐ์ด ์ฌ๋ฌ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ์คํธ๋ฆผ์ ์์ฑํ ์ ์๋ค
class StreamCreationExample {
public static void main(String[] args) {
// ํน์ ๋ฒ์์ ์ ์ ์คํธ๋ฆผ ์์ฑ
IntStream range = IntStream.range(1, 10);
// ๋์ ์คํธ๋ฆผ ์์ฑ
IntStream randomStream = new Random().ints(1, 10).limit(10);
// ๋๋ค์์ ์ฌ์ฉํ์ฌ ์คํธ๋ฆผ ์์ฑ
Stream<Integer> iterateStream = Stream.iterate(1, n -> n + 2).limit(10); // ๋๋ค์์ ์ฌ์ฉํ์ฌ ์คํธ๋ฆผ ์์ฑ
Stream<Double> generateStream = Stream
.generate(Math::random)
.limit(10); // Supplier ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ์ฌ ์คํธ๋ฆผ ์์ฑ
// ๋น ์คํธ๋ฆผ ์์ฑ
Stream<Object> emptyStream = Stream.empty();
// ๋ ์คํธ๋ฆผ ์ฐ๊ฒฐ
Stream<Integer> concatStream = Stream.concat(Stream.of(1, 2, 3), Stream.of(4, 5, 6));
}
}
์คํธ๋ฆผ์ ์ค๊ฐ ์ฐ์ฐ
์คํธ๋ฆผ์ ์ค๊ฐ ์ฐ์ฐ์ผ๋ก๋ ์๋์ ๊ฐ์ ๊ฒ๋ค์ด ์๋ค.
class IntermediateOperationsExample {
public static void main(String[] args) {
// skip()์ limit(): ์์ ๊ฑด๋๋ฐ๊ธฐ์ ์ ํ
Stream.of(1, 2, 3, 4, 5)
.skip(2)
.limit(2)
.forEach(System.out::println);
// filter()์ distinct(): ์์ ๊ฑธ๋ฌ๋ด๊ธฐ์ ์ค๋ณต ์ ๊ฑฐ
Stream.of(1, 2, 3, 4, 5, 1, 2, 3)
.filter(i -> i % 2 == 0)
.distinct()
.forEach(System.out::println);
// sorted(): ์์ ์ ๋ ฌ
Stream.of(5, 2, 1, 4, 3)
.sorted()
.forEach(System.out::println);
// map(): ์์ ๋ณํ
Stream.of(1, 2, 3, 4, 5)
.map(i -> i * 2)
.forEach(System.out::println);
// peek(): ์์ ํ์ธ (์๋นํ์ง ์์)
Stream.of(1, 2, 3, 4, 5)
.peek(System.out::println)
.forEach(System.out::println);
// mapToInt(), mapToLong(), mapToDouble(): ๊ธฐ๋ณธํ ์คํธ๋ฆผ์ผ๋ก ๋ณํ
Stream.of(1, 2, 3, 4, 5)
.mapToInt(Integer::intValue)
.forEach(System.out::println);
// flatMap(): ์คํธ๋ฆผ์ ์์๋ฅผ ๋ค๋ฅธ ์คํธ๋ฆผ์ผ๋ก ๋ณํํ๋ ์ฐ์ฐ
String[] lineArr = {
"Believe or not It is true",
"Do or do not There is no try"
};
Stream<String> lineStream = Stream.of(lineArr);
Stream<Stream<String>> strArrStream = lineStream.map(line -> Stream.of(line.split(" +")));
strArrStream.map(strStream -> Arrays.toString(strStream.toArray(String[]::new)))
.forEach(System.out::println);
// [[Believe, or, not, It, is, true], [Do, or, do, not, There, is, no, try]]
lineStream = Stream.of(lineArr);
Stream<String> stream = lineStream.flatMap(line -> Stream.of(line.split(" +")));
stream.forEach(System.out::println);
// [Believe, or, not, It, is, true, Do, or, do, not, There, is, no, try]
}
}
์คํธ๋ฆผ์ ์ต์ข
์ฐ์ฐ
์คํธ๋ฆผ์ ์์๋ฅผ ์๋ชจํด ๊ฒฐ๊ณผ๋ฅผ ๋ง๋ค์ด๋ด๊ณ , ์ต์ข
์ฐ์ฐ ํ์๋ ์คํ๋ฏธ์ด ๋ซํ๊ฒ ๋์ด ๋ ์ด์ ์ฌ์ฉํ ์ ์๋ค.
๊ฒฐ๊ณผ๋ก๋ ๋จ์ผ ๊ฐ์ด๊ฑฐ๋ ์คํธ๋ฆผ์ ์์๊ฐ ๋ด๊ธด ๋ฐฐ์ด ๋๋ ์ปฌ๋ ์
์ผ ์ ์๋ค.
class TerminalOperationsExample {
public static void main(String[] args) {
// forEach(): ์คํธ๋ฆผ ์์๋ฅผ ์๋ชจํ๋ฉด์ ์์
์ํ
Stream.of(1, 2, 3, 4, 5).forEach(System.out::println);
// allMatch(), anyMatch(), noneMatch(): ์์์ ๋ํด ์ง์ ๋ ์กฐ๊ฑด์ ๋ง๋์ง ๊ฒ์ฌํ๋ ์ฐ์ฐ์ผ๋ก boolean ๊ฐ์ ๋ฐํ
Stream.of(1, 2, 3, 4, 5).allMatch(i -> i > 0); // true
Stream.of(1, 2, 3, 4, 5).anyMatch(i -> i > 2); // true
Stream.of(1, 2, 3, 4, 5).noneMatch(i -> i > 0); // false
// findFirst()์ findAny(): ์คํธ๋ฆผ์ ์์ ์ค์์ ์ฐพ์ ์ฒซ ๋ฒ์งธ ์์๋ฅผ `Optional` ๊ฐ์ฒด๋ก ๋ฐํ(์ฐพ์ง ๋ชปํ๋ฉด empty ์ํ์ `Optional` ๊ฐ์ฒด ๋ฐํ)
Stream.of(1, 2, 3, 4, 5).findFirst(); // Optional[1]
Stream.of(1, 2, 3, 4, 5).findAny(); // Optional[1]
// reduce(): ์คํธ๋ฆผ์ ์์๋ฅผ ํ๋์ฉ ์๋ชจํ๋ฉด์ ์ง์ ๋ ๋๋ค์์ ์ํํ๋ ์ฐ์ฐ์ผ๋ก `Optional` ๊ฐ์ฒด๋ฅผ ๋ฐํ
// reduce()๋ฅผ ์ฌ์ฉํ๋ฉด sum(), max(), min() ๋ฑ์ ์ง๊ณ ์ฐ์ฐ์ ๊ตฌํํ ์ ์๋ค.
Stream.of(1, 2, 3, 4, 5).reduce((a, b) -> a + b); // Optional[15]
// count(), max(), min(): ์คํธ๋ฆผ์ ์์๋ฅผ ์๋ชจํ๋ฉด์ ์ง์ ๋ ์ฐ์ฐ์ ์ํํ๊ณ , ์ต์ข
๊ฒฐ๊ณผ๋ฅผ ๋ฐํ
Stream.of(1, 2, 3, 4, 5).count(); // 5
Stream.of(1, 2, 3, 4, 5).max(Integer::compareTo); // Optional[5]
Stream.of(1, 2, 3, 4, 5).min(Integer::compareTo); // Optional[1]
// collect(): ์คํธ๋ฆผ์ ์์๋ฅผ ์์งํ๋ ์ฐ์ฐ์ผ๋ก, `Collector`๋ฅผ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์ ๋ฐ์ ํ์
์ผ๋ก ๋ณํํ์ฌ ๋ฐํ
List<Integer> list = Stream.of(1, 2, 3, 4, 5).collect(Collectors.toList());
Set<Integer> set = Stream.of(1, 2, 3, 4, 5).collect(Collectors.toSet());
}
}
findFirst() vs findAny()
findFirst()
์ findAny()
๋ ๋ฉ์๋ ๋ชจ๋ ์ฐพ์ ์ฒซ ๋ฒ์งธ ์์๋ฅผ Optional
๊ฐ์ฒด๋ก ๋ฐํํ๋ค.
ํ์ง๋ง ๋ณ๋ ฌ ํ๊ฒฝ์์ ์ฒ๋ฆฌ๋ฅผ ํ ๋๋ ๋ ๋ฉ์๋์ ์๋์ ๊ฐ์ ์ฐจ์ด๊ฐ ๋ฐ์ํ๊ฒ ๋๋ค.
findFirst()
: ์ฌ๋ฌ ์์๊ฐ ์กฐ๊ฑด์ ๋ถํฉํด๋ Stream์ ์์๋ฅผ ๊ณ ๋ คํ์ฌ ์ฒซ ๋ฒ์งธ ์์๋ฅผ ๋ฐํ
findAny()
: Multiple Thread์์ ์ฌ๋ฌ ์์๋ฅผ ์ฒ๋ฆฌํ๋ค๊ฐ ๊ฐ์ฅ ๋จผ์ ์ฐพ์ ์์๋ฅผ ๋ฐํ
class FindFirstAndFindAnyExample {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Optional<Integer> findFirst = list.stream().parallel().filter(i -> i % 2 == 0).findFirst();
Optional<Integer> findAny = list.stream().parallel().filter(i -> i % 2 == 0).findAny();
System.out.println(findFirst.get()); // 2
System.out.println(findAny.get()); // 2, 4, 6, 8, 10 ์ค ํ๋
}
}
์ฐธ๊ณ ์๋ฃ