⭐스트림이란?
- 데이터의 흐름
- 컬렉션(Collection) 형태로 구성된 데이터를 람다를 이용해 간결하고 직관적으로 프로세스하게 해줌
- For, while 등을 이용하던 기존 loop을 대체
- 손쉽게 병렬 처리를 할 수 있게 해줌
☀️Stream의 구성요소

List<String> emails2 = users.stream()
.filter(user -> !user.isVerified())
.map(User::getEmailAddress)
.collect(Collectors.toList());
List<Order> ex2 = orders.stream()
.filter(order -> order.getStatus() == OrderStatus.ERROR)
.filter(order -> order.getCreatedAt().isAfter(now.minusHours(24)))
.collect(Collectors.toList());
📑Stream의 다양한 중간 처리
1. Filter
- 인스타그램 필터 말고 거름종이같은 필터
- 만족하는 데이터만 걸러내는데 사용
- Predicate에 true를 반환하는 데이터만 존재하는 stream을 리턴
Stream<T> filter(Predicate<? super T> predicate);
Stream<Integer> numberStream = Stream.of(3, -5, 7, 10, -3);
Stream<Integer> filteredNumberStream = numberStream.filter(x -> x > 0);
List<Integer> filteredNumbers = filteredNumberStream.collect(Collectors.toList());
List<Integer> newFilteredNumbers = Stream.of(3, -5, 7, 10, -3)
.filter(x -> x > 0)
.collect(Collectors.toList());
List<User> users = Arrays.asList(user1, user2, user3);
List<User> verifiedUsers = users.stream()
.filter(User::isVerified)
.collect(Collectors.toList());
List<Order> errorOrder = orders.stream()
.filter(o -> o.getStatus() == OrderStatus.ERROR)
.collect(Collectors.toList());
2. Map
- 데이터를 변형하는데 사용
- 데이터에 해당 함수가 적용된 결과물을 제공하는 stream을 리턴
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
var numberList = Arrays.asList(3, 6, -4);
List<Integer> numberListX2 = numberList.stream()
.map(x -> x * 2)
.collect(Collectors.toList());
List<String> emailAddresses = users.stream()
.map(User::getEmailAddress)
.collect(Collectors.toList());
3. Sorted
- 데이터가 순서대로 정렬된 stream을 리턴
- 데이터의 종류에 따라 Comparator가 필요할 수 있음
Stream<T> sorted();
Stream<T> sorted(Comparator<? super T> comparator);
List<Integer> numbers = Arrays.asList(3, -5, 7, 4);
List<Integer> sortedNumbers = numbers.stream()
.sorted()
.collect(Collectors.toList());
List<User> users = Arrays.asList(user1, user2, user3);
List<User> sortedUsers = users.stream()
.sorted((u1, u2) -> u2.getName().compareTo(u1.getName()))
.collect(Collectors.toList());
4. Distinct
Stream<T> distinct();
List<Long> ex = orders.stream()
.map(Order::getCreatedByUserId)
.distinct()
.sorted()
.collect(Collectors.toList());
5. FlatMap
- Map + Flatten
• 데이터에 함수를 적용한 후 중첩된 stream을 연결하여 하나의 stream으로 리턴
<R> Stream<R> flatMap(
Function<? super T, ? extends Stream<? extends R>> mapper);
☠️NPE – NullPointerException
- Null 상태인 오브젝트를 레퍼런스 할 때 발생
- Runtime error이기 때문에 실행 전 까지는 발생 여부를 알기 쉽지 않음
😊Optional
1. Optional이란?
- Null일수도, 아닐 수도 있는 오브젝트를 담은 상자
java.util.Optional<T>
Optional<String> maybeString = Optional.of("Hello world");
String string = maybeString.get();
2. Optional 만드는 법
public static <T> Optional<T> of(T value)
public static <T> Optional<T> empty()
public static <T> Optional<T> ofNullable(T value)
String someEmail = "some@email.com";
String nullEmail = null;
Optional<String> maybeEmail = Optional.of(someEmail);
Optional<String> maybeEmail2 = Optional.empty();
Optional<String> maybeEmail3 = Optional.ofNullable(someEmail);
Optional<String> maybeEmail4 = Optional.ofNullable(nullEmail);
- of – Null이 아닌 오브젝트를 이용해 Optional을 만들 때
- Empty – 빈 Optional을 만들 때
- ofNullable – Null인지 아닌지 알 지 못하는 오브젝트로 Optional을 만들 때
3. 안에 있는 값을 확인하고 꺼내는 법
public boolean isPresent()
public T get()
public T orElse(T other)
public T orElseGet(Supplier<? extends T> supplier)
public <X extends Throwable> T orElseThrow(
Supplier<? extends X> exceptionSupplier) throws X
String email = maybeEmail.get();
System.out.println(email);
if (maybeEmail2.isPresent()) {
System.out.println(maybeEmail2.get());
}
String defaultEmail = "default@email.com";
String email3 = maybeEmail2.orElse(defaultEmail);
System.out.println(email3);
String email4 = maybeEmail2.orElseGet(() -> defaultEmail);
System.out.println(email4);
String email5 = maybeEmail2.orElseThrow(() -> new RuntimeException("email not present"));
- isPresent – 안의 오브젝트가 null인지 아닌지 체크. Null이 아닐 시 true
- get – Optional 안의 값을 추출. Null이라면 에러
- orElse – Optional이 null이 아니라면 Optional 안의 값을, null이라면 other로 공급된 값을 리턴
- orElseGet – Optional이 null이 아니라면 Optional 안의 값을, null이라면 supplier로 공급되는 값을 리턴
- orElseThrow – Optional이 null이 아니라면 Optional 안의 값을, null이라면 exceptionSupplier로 공급되는 exception을 던짐
4. 응용을 위해 알아야 할 것들
public void ifPresent(Consumer<? super T> action)
public <U> Optional<U> map(Function<? super T, ? extends U> mapper)
public <U> Optional<U> flatMap(
Function<? super T, ? extends Optional<? extends U>> mapper)
Optional<User> maybeUser = Optional.ofNullable(maybeGetUser(true));
maybeUser.ifPresent(user -> System.out.println(user));
Optional<Integer> maybeId = Optional.ofNullable(maybeGetUser(true))
.map(user -> user.getId());
maybeId.ifPresent(System.out::println);
String userName = Optional.ofNullable(maybeGetUser(false))
.map(User::getName)
.map(name -> "The name is " + name)
.orElse("Name is empty");
System.out.println(userName);
Optional<String> maybeEmail = Optional.ofNullable(maybeGetUser(true))
.flatMap(User::getEmailAddress);
maybeEmail.ifPresent(System.out::println);
- ifPresent – Optional이 null이 아니라면 action을 실행
- map – Optional이 null이 mapper를 적용
- flatMap – mapper의 리턴 값이 또 다른 Optional이라면 한 단계의 Optional이 되도록 납작하게 해줌