● 스트림Stream
스트림은 데이터가 흘러가는 줄기예요.
데이터가 흘러 들어가서 결과를 출력하기까지의 과정이 담긴 줄기입니다.
마치 파이프를 연결해놓고, 그 사이에 필터를 넣을 수 있는 것처럼
스트림 안에도 필터를 끼어서 원하는 결과만을 얻을 수도 있어요.
스트림을 생성하고 이를 대상으로 ‘중간 연산’과 ‘최종 연산’을 진행하면, 원하는 기준으로 데이터를 필
터링하고 필터링 된 데이터의 가공된 결과를 얻을 수 있습니다.
중간 연산 성격의 메소드가 있고, 최종 연산 성격의 메소드가 있습니다.
아래의 예시를 같이 보겠습니다.
public static void main(String[] args) { int[] ar = {1, 2, 3, 4, 5}; IntStream stm1 = Arrays.stream(ar); // 배열 ar로부터 스트림 생성. IntStream 은 Stream의 참조형. 배열에서 스트림을 뽑아내는 스테틱 메소드 사용. IntStream stm2 = stm1.filter(n -> n%2 == 1); // 중간 연산 진행. 주어진 기능을 토대로 해서 걸러냅니다. true 만 다시 흘러내려갑니다. int sum = stm2.sum(); // 최종 연산 진행. 최종 연산을 생략하면 아무 결과도 얻지 못합니다. System.out.println(sum); } |
이 과정을 메소드 체인으로 표현하자면 다음과 같습니다.
표현방식은 일종의 약속과도 같습니다. (조금 더 선호되는 방법!)
public static void main(String[] args) { int[] ar = {1, 2, 3, 4, 5}; int sum = Arrays.stream(ar) // 스트림 생성, .filter(n -> n%2 == 1) // filter 통과, .sum(); // sum 통과 결과 반환 System.out.println(sum); } |
● 이제 조금 더 구체적으로 배열 대상 스트림의 생성에 있어서 기본적인 구조를 살펴볼게요.
우선 배열 대상 스트림입니다.
배열 대상 스트림 대표 메소드는 다음과 같습니다.
public static <T> Stream<T> stream(T[] array) // Arrays 클래스에 정의
public static void main(String[] args) {
String[] names = {"YOON", "LEE", "PARK"}; // 배열 생성
Stream<String> stm = Arrays.stream(names); // 스트림 생성
stm.forEach(s -> System.out.println(s)); // 최종 연산 진행
}
이것을 메소드 체인으로 연결해서 실제로는 이렇게 코딩합니다.
public static void main(String[] args) {
String[] names = {"YOON", "LEE", "PARK"};
Arrays.stream(names)
.forEach(s -> System.out.println(s));
}
스트림은 배열을 대상으로 활용할 수 있는 다양한 메소드들이 존재합니다.
Arrays 클래스에 정의된 메소드들은 다음과 같습니다.
- public static IntStream stream(int[] array)
- public static IntStream stream(int[] array, int startInclusive, int endExclusive)
- public static DoubleStream stream(double[] array)
- public static DoubleStream stream(double[] array, int startInclusive, int endExclusive)
- public static LongStream stream(double[] array)
- public static LongStream stream(double[] array, int startInclusive, int endExclusive)
이에 대한 예시를 코드를 통해 확인해볼게요.
인덱스를 지정할 때에는 시작하는 인덱스는 포함하지만 끝나는 인덱스는 그 앞까지만 포함한다는 것을 참고해야 해요.
public static void main(String[] args) {
double[] ds = {1.1, 2.2, 3.3, 4.4, 5.5}; // 배열 생성
Arrays.stream(ds) // ds로 스트림 생성
.forEach(d -> System.out.print(d + "\t")); // 최종 연산 진행
System.out.println(); // 줄바꿈
Arrays.stream(ds, 1, 4) // 인덱스 1부터 인덱스 4 이전까지의 배열로 스트림 생성
.forEach(d -> System.out.print(d + "\t")); // 최종 연산 진행
System.out.println(); // 줄바꿈
}
● 컬렉션 인스턴스 배열에 대해서 확인해볼게요.
컬렉션 인스턴스를 대상으로 스트림을 생성할 때 호출하는 메소드는 다음과 같습니다.
default Stream<E> stream() // java.util.Collection<E>의 디폴트 메소드 (컬렉션 인터페이스에 정의가 되어 있다.)
public static void main(String[] args) {
List<String> list = Arrays.asList("Toy", "Robot", "Box");
list.stream()
.forEach(s -> System.out.print(s + "\t"));
System.out.println();
}
● 필터링은 중간 연산입니다.
즉 스트림을 구성하는 데이터 중 일부를 조건에 따라 걸러내는 연산이에요.
Stream<T> filter(Predicate<? super T> predicate) // Stream<T>에 존재
// Predicate<T> boolean test(T t) 불리언 결과를 반환하는 Predicate 함수라고 한다면
public static void main(String[] args) {
int[] ar = {1, 2, 3, 4, 5};
Arrays.stream(ar) // 배열 기반 스트림 생성
.filter(n -> n%2 == 1) // 홀수만 통과시킵니다.
.forEach(n -> System.out.print(n + "\t"));
System.out.println();
List<String> sl = Arrays.asList("Toy", "Robot", "Box");
sl.stream() // 컬렉션 인스턴스 기반 스트림 생성
.filter(s -> s.length() == 3) // 길이가 3이면 통과시킵니다.
.forEach(s -> System.out.print(s + "\t"));
System.out.println();
}
맵핑은 주어진 것을 가지고 새로운 데이터를 하나씩 만드는 연산이에요.
public static void main(String[] args) {
List<String> ls = Arrays.asList("Box", "Robot", "Simple");
ls.stream()
.map(s -> s.length()) // 주어진 인수에 길이를 반환합니다.
.forEach(n -> System.out.print(n + "\t"));
System.out.println(); // 최종 출력 연산
}
수월한 맵핑을 위한 키워드가 있습니다.
IntStream mapToInt(ToIntFunction<? super T> mapper) // Int 형을 반환하는 맵핑
LongStream mapToLong(ToLongFunction<? super T> mapper) // Long 형을 반환하는 맵핑
DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper) //Double 형을 반환하는 맵핑
필터링 후 맵핑에 대한 예제를 하나 보겠습니다.
import java.util.List;
import java.util.ArrayList;
class ToyPriceInfo { // 모델과 가격에 대한 선언
private String model;
private int price;
public ToyPriceInfo(String m, int p) {
model = m;
price = p;
}
public int getPrice() { // 가격의 자료 반환
return price;
}
}
class ToyStream {
public static void main(String[] args) {
List<ToyPriceInfo> ls = new ArrayList<>(); // 배열 생성
ls.add(new ToyPriceInfo("GUN_LR_45", 200)); // 배열에 요소들 추가
ls.add(new ToyPriceInfo("TEDDY_BEAR_S_014", 350));
ls.add(new ToyPriceInfo("CAR_TRANSFORM_VER_7719", 550));
int sum = ls.stream() // 스트림 생성
.filter(p -> p.getPrice() < 500) // 필터생성
.mapToInt(t -> t.getPrice()) // 중간 맵핑
.sum();
System.out.println("sum = " + sum); // 최종 결과 출력
}
}
'자바 > 자바 입문 공부일지' 카테고리의 다른 글
자바 기초 공부 일지 52. 버퍼 (작성 수정중) (0) | 2022.11.08 |
---|---|
자바 기초 공부 일지 51. 리덕션, 맵핑Mapping (Map, faltMap) (작성중) (0) | 2022.11.07 |
자바 기초 공부 일지 49. 메소드 참조 (작성 수정중) (0) | 2022.11.07 |
자바 기초 공부 일지 48. 함수형 인터페이스 Predicate<T>, Supplier<T>, Consumer<T>, Function<T, R> (2) | 2022.11.04 |
자바 기초 공부 일지 47. 람다와 함수형 인터페이스 (0) | 2022.11.04 |