1. 스트림
▷ Java8부터 컬렉션 및 배열의 요소를 반복 처리하기 위해 스트림 사용
▷ 요소들이 하나씩 흘러가면서 처리된다는 의미
▷ List 컬렉션의 stream() 메소드로 Stream 객체를 얻고, forEach() 메소드로 요소를 어떻게 처리할지 람다식으로 제공
▷ 스트림과 Iterator 차이점
▶ 내부 반복자이므로 처리 속도가 빠르고 병렬 처리에 효율적
▶ 람다식으로 다양한 요소 처리를 정의
▶ 중간 처리와 최종 처리를 수행하도록 파이프 라인을 형성
◎ 스트림 사용 예제
import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.stream.Stream; public class StreamExample { public static void main(String[] args) { // Set 컬렉션 생성 Set<String> set = new HashSet<>(); set.add("홍길동"); set.add("신용권"); set.add("감자바"); // Iterator 사용 : set 이용시 많이 사용 방법 Iterator<String> iterator = set.iterator(); while(iterator.hasNext()) { String item = iterator.next(); System.out.println(item); } System.out.println(); // Stream을 이용한 요소 반복 처리 Stream<String> stream = set.stream(); stream.forEach(name -> System.out.println(name)); } } // 출력 : // 홍길동 // 신용권 // 감자바 // // 홍길동 // 신용권 // 감자바
▷ Iiterator는 하나씩 불러와서 저장하는 것이라면 Stream은 연결해서 불러오는 것이라고 생각하면 됩니다.
2. 내부 반복자
▷ 요소 처리 방법을 컬렉션 내부로 주입시켜서 요소를 반복 처리
▷ 개발자 코드에서 제공한 데이터 처리 코드(람다식)를 가지고 컬렉션 내부에서 요소를 반복 처리
▷ 내부 반복자는 멀티 코어 CPU를 최대한 활용학 위해 요소들을 분배시켜 병렬 작업 가능
◎ 내부 반복자 사용 예제(스레드 사용)
import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; public class ParallelStreamExample { public static void main(String[] args) { // List 컬렉션 생성 List<String> list = new ArrayList<>(); list.add("홍길동"); list.add("신용권"); list.add("감자바"); list.add("람다식"); list.add("박병렬"); // 기존 방식 for(int i=0; i<list.size(); i++) { String item = list.get(i); System.out.println(item); } System.out.println(); // 병렬 처리 Stream<String> parallelStream = list.parallelStream(); parallelStream.forEach(name -> { System.out.println(name + ": " + Thread.currentThread().getName()); }); } } // 출력 : // 홍길동 // 신용권 // 감자바 // 람다식 // 박병렬 // // 감자바: main // 람다식: main // 홍길동: main // 박병렬: ForkJoinPool.commonPool-worker-2 // 신용권: ForkJoinPool.commonPool-worker-1
▷ currentThread는 실행할때마다 현재 스레드명이 바뀝니다.
▷ 내부 반복자는 멀티 코어 CPU를 최대한 활용하기 위해 요소들을 분배시켜 병렬 작업을 할 수 있습니다.
▷ 하나씩 처리하는 순차적 외부 반복자보다는 효율적으로 요소를 반복시킬 수 있습니다.
3. 스트림 파이프라인
▷ 컬렉션의 오리지널 스트림 뒤에 필터링 중간 스트림이 연결될 수 있고, 그 뒤에 매핑 중간 스트림이 연결될 수 있음
▷ 오리지널 스트림과 집계 처리 사이의 중간 스트림들은 최종 처리를 위해 요소를 걸러내거나(필터링), 요소를 변환시키거나(매핑), 정렬하는 작업을 수행
▷ 최종 처리는 중간 처리에서 정제된 요소들을 반복하거나, 집계(카운팅, 총합, 평균) 작업을 수행
◎ 파이프라인 사용 예제
1. Student 클래스
public class Student { private String name; private int score; public Student (String name, int score) { this.name = name; this.score = score; } public String getName() { return name; } public int getScore() { return score; } }
2. StreamPipeLineExample 메인 클래스
import java.util.Arrays; import java.util.List; import java.util.stream.IntStream; import java.util.stream.Stream; public class StreamPipeLineExample { public static void main(String[] args) { List<Student> list = Arrays.asList( new Student("홍길동", 10), new Student("신용권", 20), new Student("유미선", 30) ); // 방법1 /* Stream<Student> studentStream = list.stream(); // 중간 처리(학생 객체를 점수로 매핑) IntStream scoreStream = studentStream.mapToInt(student -> student.getScore()); // 최종 처리(평균 점수) double avg = scoreStream.average().getAsDouble(); */ // 방법2 double avg = list.stream() .mapToInt(stu -> stu.getScore()) .average() .getAsDouble(); System.out.println("평균 점수: " + avg); } } // 출력 : // 평균 점수: 20.0
▷ stream은 list를 쭉 연결해서 가져오고 mapping 되어있는 값 중 int 값을 찾고 평균을 구합니다.
4. 리소스로부터 스트림 얻기
◎ 스트림 인터페이스
▷ java.util.stream 패키지에는 BaseStream 인터페이스를 부모로 한 자식 인터페이스들은 상속 관계
▷ BaseStream에는 모든 스트림에서 사용할 수 있는 공통 메소드들이 정의
NO | 리턴 타입 | 메소드(매개변수) | 소스 |
1 | Stream<T> | java.util.Collection.stream() java.util.Collection.parallelStream() |
List 컬렉션 Set 컬렉션 |
2 | Stream<T> IntStream LongStream DoubleStream |
Arrays.stream(T[ ]), Stream.of(T[ ]) Arrays.stream(int[ ]), IntStream.of(int[ ]) Arrays.stream(long[ ]), LongStream.of(long[ ]) Arrays.stream(double[ ]), DoubleStream.of(double[ ]) |
배열 |
3 | IntStream | IntStream.range(int, int) IntStream.rangeClosed(int, int) |
int 범위 |
4 | LongStream | LongStream.range(long, long) LongStream.rangeClosed(long, long) |
long 범위 |
5 | Stream<Path> | Files.list(Path) | 디렉토리 |
6 | Stream<String> | Files.lines(Path, Charset) | 텍스트 파일 |
7 | DoubleStream IntStream LongStream |
Random.doubles(...) Random.ints() Random.longs() |
랜덤 수 |
◎ 컬렉션으로부터 스트림 얻기
▷ java.util.Collection 인터페이스는 스트림과 parallelStream() 메소드를 가지고 있어
자식 인터페이스인 List와 Set 인터페이스를 구현한 모든 컬렉션에서 객체 스트림을 얻을 수 있습니다.
1. Product 클래스
public class Product { private int pno; private String name; private String company; private int price; public Product(int pno, String name, String company, int price) { this.pno = pno; this.name = name; this.company = company; this.price = price; } public int getPno() { return pno; } public String getName() { return name; } public String getCompany() { return company; } public int getPrice() { return price; } @Override public String toString() { return new StringBuilder() .append("{") .append("pno:" + pno + ",") .append("name:" + name + ",") .append("company:" + company + ",") .append("price:" + price) .append("}") .toString(); } }
2. StreamExample 메인 클래스import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; public class StreamExample { public static void main(String[] args) { // List 컬렉션 생성 List<Product> list = new ArrayList<>(); for(int i=1; i<=5; i++) { Product product = new Product(i, "상품"+i, "멋진 회사 ", (int)(10000*Math.random())); list.add(product); } // 객체 스트림 얻기 Stream<Product> stream = list.stream(); stream.forEach(p -> System.out.println(p)); } } // 출력 : // {pno:1,name:상품1,company:멋진 회사 ,price:3848} // {pno:2,name:상품2,company:멋진 회사 ,price:2207} // {pno:3,name:상품3,company:멋진 회사 ,price:5000} // {pno:4,name:상품4,company:멋진 회사 ,price:2853} // {pno:5,name:상품5,company:멋진 회사 ,price:5950}
◎ 배열로부터 스트림 얻기
▷ java.util.Arrays 클래스로 다양한 종류의 배열로부터 스트림을 얻을 수 있습니다.
package stream3; import java.util.Arrays; import java.util.stream.IntStream; import java.util.stream.Stream; public class StreamExample { public static void main(String[] args) { String[] strArray = {"홍길동", "신용권", "김미나"}; System.out.println("String 배열 내용 출력"); Stream<String> strStream = Arrays.stream(strArray); strStream.forEach(item -> System.out.print(item + ",")); System.out.println(); System.out.println(); int[] intArray = { 1, 2, 3, 4, 5 }; System.out.println("Int 배열 내용 출력"); IntStream intStream = Arrays.stream(intArray); intStream.forEach(item -> System.out.print(item + ",")); } } // 출력 : // String 배열 내용 출력 // 홍길동,신용권,김미나, // // Int 배열 내용 출력 // 1,2,3,4,5,
◎ 숫자 범위로부터 스트림 얻기
▷ IntStream 또는 LongStream의 정적 메소드인 range()와 rangeClosed() 메소드로 특정 범위의 정수 스트림을 얻을 수 있습니다.
range(1, 10); 1~9 : 끝 수를 포함하지 않는다.
rangeClosed(1, 10); 1~10 : 끝 수를 포함한다.
import java.util.stream.IntStream; public class StreamExample { public static int sum; public static void main(String[] args) { IntStream stream = IntStream.rangeClosed(1, 100); stream.forEach(a -> sum += a); System.out.println("총합: " + sum); sum = 0; IntStream stream1 = IntStream.range(1, 100); stream1.forEach(a -> sum += a); System.out.println("총합: " + sum); } } // 출력 : // 총합: 5050 // 총합: 4950
◎ 파일로부터 스트림 얻기
▷ java.nio.file.Files의 lines() 메소드로 텍스트 파일의 행 단위 스트림을 얻을 수 있습니다.
1. data.txt
{"pno":1,"name":"상품1","company":"멋진 회사" ,"price":1357} {"pno":2,"name":"상품2","company":"멋진 회사" ,"price":2057} {"pno":3,"name":"상품3","company":"멋진 회사" ,"price":6995} {"pno":4,"name":"상품4","company":"멋진 회사" ,"price":1843} {"pno":5,"name":"상품5","company":"멋진 회사" ,"price":3863}
2. StreamExample 메인 클래스
▷ key와 value가 있는 json이나 map 형식과 비슷합니다.
import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Stream; public class StreamExample { public static void main(String[] args) throws Exception { Path path = Paths.get(StreamExample.class.getResource("data.txt").toURI()); Stream<String> stream = Files.lines(path, Charset.defaultCharset()); stream.forEach(line -> System.out.println(line)); stream.close(); } }
결과 값은 데이터 파일과 동일하게 출력됩니다.
스트림에 대해서 시작해보았는데요 Iterator와 비슷한 것 같죠?
다음 강의에서 좀 더 알아볼게요~!!
많은 분들의 피드백은 언제나 환영합니다! 많은 댓글 부탁드려요~~

'BackEnd > Java' 카테고리의 다른 글
[백준 문제 10250번] ACM 호텔 문제 (0) | 2023.01.29 |
---|---|
[java] 이것이 자바다 ch17 스트림(필터링, 매핑, wrapper) (0) | 2023.01.28 |
[java] 이것이 자바다 ch16 람다식(rambda) (0) | 2023.01.27 |
[java] 이것이 자바다 ch15 컬렉션 3 (0) | 2023.01.26 |
[java] 이것이 자바다 ch15 컬렉션 2 (0) | 2023.01.26 |