728x90
스트림 API란?
여러 종류의 데이터를 다양한 방식으로 다룰 수 있도록 제공하는 표준화된 방법 (≥ JDK 1.8)
- 배열이나 컬렉션 뿐만 아니라 파일 데이터도 가능
- 반복문이나 반복자(iterator)를 사용하여 개발하지 않아도 되도록 지원
import java.util.Arrays;
public class BasicStreamExample {
public static void main(String[] args) {
String[] stringArray = {"this", "is", "a", "stream", "example", "is", "this"};
Arrays.stream(stringArray).distinct().forEach(System.out::println);
int[] numArray = {1, 2, 3, 4, 5, 6, 1, 2, 3};
int sum = Arrays.stream(numArray).distinct().sum();
System.out.println(sum);
}
}
- distinct : 중복 제거
스트림 API 특징
- 원본 데이터 변경 불가능
- 일회용
- 병렬 처리 가능
- 내부 반복으로 작업 처리
- 기본 데이터형을 처리할 수 있는 래퍼 스트림 지원 (Int/Double/LongStream)
스트림 API 연산 과정
스트림 생성 → 중개 연산(스트림의 변환) → 최종 연산(스트림의 사용)
스트림 생성 | 중개 연산 | 최종 연산 |
Array | Filtering | Calculating |
List | Mapping | Collecting |
File | Sorting | Reducing |
Random | Splitting | Matching |
etc. | Iterating | Iterating |
스트림 생성
스트림을 사용하기 위해서는 아래의 여러 원본 데이터를 이용해 스트림 형태로 만들어야 함
- 컬렉션, 배열
- 가변 매개변수
- 지정된 범위의 연속된 정수
- 난수들
- 람다 표현식
- 파일
- 빈 스트림
import java.util.*;
public class CreationStreamExample {
public static void main(String[] args) {
// 배열에서 스트림 생성
String[] arr = new String[]{"a", "b", "c", "d"};
Stream<String> arrayToStream = Arrays.stream(arr);
// Collection에서 스트림 생성
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> listToStream = list.stream();
// 지정된 범위의 연속된 정수에서 스트림 생성
IntStream continuousIntStream = IntStream.rangeClosed(1, 4);
// 특정 타입의 난수로 이루어진 스트림 생성
IntStream randomStream = new Random().ints(4);
// 람다를 이용한 스트림 생성 generate
Stream<Integer> lambdaIterate = Stream.iterate(0, n -> n + 1);
Stream<Double> lambdaGenerateStream = Stream.generate(Math::random); //error
// 파일 스트림 생성
try {
Stream<String> fileStream = Files.lines(Paths.get("path"));
} catch (IOException e) {
throw new RuntimeException(e);
}
// 빈 스트림 생성
Stream emptyStream = Stream.empty();
}
}
스트림 중개 연산
앞에서 생성된 초기 스트림을 전달받아 필터링이나 변환 등의 연산을 수행
- Filtering
- Mapping
- Sorting
- Splitting
- Iterating
Filtering
- filtering() : 주어진 조건에 참인 요소를 필터링
- distinct() : 스트림의 중복 요소를 제거
Mapping
- map() : map에 명령문을 인수로 전달하여, 반환값들로 구성된 새로운 스트림을 반환
- flatMap() : 스트림 요소가 배열인 경우, 주어진 명령문을 적용한 새로운 스트림으로 반환
import java.util.stream.*;
public class IntermediateOperationExample {
public static void main(String[] args) {
String[] names = {"a", "b", "ab", "ab", "c"};
System.out.println("Filtering");
Stream<String> filterStream = Stream.of(names);
filterStream.filter(name -> name.contains("a")).forEach(System.out::println);
System.out.println("Distinct");
Stream<String> distinctStream = Stream.of(names);
distinctStream.distinct().forEach(System.out::println);
System.out.println("Map");
IntStream mapStream = IntStream.of(7, 3, 5, 4, 6);
mapStream.map(num -> num + 2).forEach(System.out::println);
System.out.println("flatMap");
String[] wordArray = {"this is", "Intermediate Operation", "java jdk1.8"};
Stream<String> flatMapStream = Stream.of(wordArray);
flatMapStream.flatMap(s -> Stream.of(s.split(" "))).forEach(System.out::println);
}
}
Sorting
- sorted() : Comparator를 구현하여 넘겨주거나 natural order로 정렬
Splitting
- limit() : 스트림에서 limit에 들어가는 수만큼의 새로운 스트림을 반환
- skip() : 스트림의 첫 요소부터 skip에 들어가는 수를 제외한 새로운 스트림을 반환
Iterating
- peek() : 각 요소를 돌면서 peek에 전달된 명령문을 수행
import java.util.stream.*;
public class IntermediateOperationExample {
public static void main(String[] args) {
System.out.println("Sorted");
IntStream unsortedStream = IntStream.of(7, 3, 5, 4, 6);
unsortedStream.sorted().forEach(System.out::println);
System.out.println("limit");
IntStream limitStream = IntStream.of(7, 3, 5, 4, 6);
limitStream.limit(3).forEach(System.out::println);
System.out.println("skip");
IntStream skipStream = IntStream.of(7, 3, 5, 4, 6);
skipStream.skip(3).forEach(System.out::println);
System.out.println("peek");
IntStream peekStream = IntStream.of(7, 3, 5, 4, 6);
peekStream.sorted().peek(i -> System.out.println("sorted 수행 : " + i)
.forEach(System.out::println);
}
}
스트림 최종 연산
앞에서 수행된 중개 스트림을 전달받아 최종적인 연산을 진행하여 이저의 스트림을 사용할 수 없게 됨
- Calculating
- Collecting
- Reducing
- Matching
- Iterating
Calculating
- count(), min(), max() : 요소의 개수와 최댓값, 최솟값을 반환
- sum(), average() : 요소들의 합과 평균 값을 반환
Collecting
- collect() : 매개변수로 Collectors의 구현 메소드를 받아 메소드의 동작대로 요소를 수집하여 반환
Reducing
- reduce() : 스트림의 첫 두 요소를 가지고 여산 후, 이후 요소들로 연산한 값을 반환
import java.util.*;
import java.util.stream.*;
public class TerminateOperationExample {
public static void main(String[] args) {
System.out.println("count");
IntStream countStream = IntStream.of(7, 3, 5, 4, 6);
System.out.println(countStream.skip(2).count());
System.out.println("average");
IntStream averageStream = IntStream.of(7, 3, 5, 4, 6);
OptionalDouble averageResult = averageStream.skip(2).average();
System.out.println(averageResult.getAsDouble());
System.out.println("collect");
IntStream collectStream = IntStream.of(7, 3, 5, 4, 6);
List<Integer> collectedList = collectStream.sorted().boxed()
.collect(Collectors.toList());
for (int element : collectedList) {
System.out.println(element);
}
System.out.println("reduce");
IntStream reduceStream = IntStream.of(7, 3, 5, 4, 6);
Optional<Integer> reduceResult = reduceStream.sorted().boxed()
.reduce((num1, num2) -> num1 * num2);
System.out.println(reduceResult.get());
}
}
Matching
- anyMatch() : 스트림이 일부 요소가 특정 조건을 만족하면 true를 반환
- allMatch() : 스트림이 모든 요소가 특정 조건을 만족하면 true를 반환
- noneMatch() : 스트림이 모든 요소가 특정 조건을 만족하지 않으면 true를 반환
- findFirst() : 스트림의 첫 요소를 반환
- findAny() : 스트림의 첫 요소를 반환하는 것 같지만 parallelStream의 경우에 쓰임
Iterating
- foreach() : 각 요소를 돌면서 foreach에 전달된 명령문을 수행
import java.util.*;
import java.util.stream.*;
public class TerminateOperationExample {
public static void main(String[] args) {
System.out.println("anyMatch");
IntStream anyMatchStream = IntStream.of(7, 3, 5, 4, 6);
System.out.println(anyMatchStream.anyMatch(n -> n % 2 == 1));
System.out.println("allMatch");
IntStream allMatchStream = IntStream.of(7, 3, 5, 4, 6);
System.out.println(allMatchStream.allMatch(n -> n / 2 == 1));
System.out.println("findFirst");
IntStream findFirstStream = IntStream.of(7, 3, 5, 4, 6);
OptionalInt findFirstResult = findFirstStream.sorted().findFirst();
System.out.println(findFirstResult.getAsInt());
System.out.println("findAny");
IntStream findAnyStream = IntStream.of(7, 3, 5, 4, 6);
OptionalInt findAnyResult = findAnyStream.sorted().findAny();
System.out.println(findAnyResult.getAsInt());
}
}
Optional 클래스
Null값으로 인한 예외를 회피할 수 있는 래퍼 클래스
- 모든 타입의 참조 변수를 저장 가능
- 메소드를 이용하여 NullPointerException을 회피 가능
- Stream과 비슷하게 기본 데이터혀을 처리할 수 있는 래퍼 클래스 지원
import java.util.*;
public class OptionalExample {
public static void main(String[] args) {
Optional<String> optionalNullStr = Optional.ofNullable(null);
Optional<String> optionalStr = Optional.ofNullable("null");
Optional<Integer> optionalInt = Optional.of(0);
OptionalDouble optionalDouble = OptionalDouble.of(3.14);
// Optional 객체의 값이 null인지 여부 반환
System.out.println(optionalNullStr.isPresent());
// Optional 객체의 값이 null이면 매개변수 출력
System.out.println(optionalNullStr.orElse("NULL값"));
// Optional 객체의 값이 존재하면 매개변수로 전달된 명령문 수행
optionalStr.isPresent(System.out::println);
// Optional 값 출력
System.out.println(optionalInt.get());
// OptionalDouble 값 출력
System.out.println(optionalDouble.getAsDouble());
}
}
P. 특정 수를 입력 받고 해당 숫자 안의 모든 소수를 list로 만드는 스트림 작성
Condition
- 반환된 스트림을 print문으로 출력
import java.util.*;
public class Problem {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int bound = sc.nextInt();
List<Integer> result = calculatePrimeNumbers(bound);
for (int i : result) {
System.out.println(i);
}
}
public static List<Integer> calculatePrimeNumbers(int n) {
return IntStream.rangeClosed(2, n)
.filter(x -> isPrimeNumber(x)).boxed()
.collect(Collectors.toList());
}
private static boolean isPrimeNumber(int number) {
return Intstream.rangeClosed(2, (int)(Math.sqrt(number)))
.allMatch(n -> number % n != 0);
}
}
'JAVA > Java Study' 카테고리의 다른 글
[Java] Map을 Key, Value로 정렬하기 (0) | 2024.08.18 |
---|---|
[Java] Map 순회 방법 (0) | 2024.08.18 |
[Java] 람다 표현식(Lambda Expression) (0) | 2024.06.24 |
[Java] List에 특정 값이 포함되어 있는지 확인하는 방법 (0) | 2024.05.20 |
[Java] 조합 Combination 구현하기! (1) | 2024.04.19 |