동작 | 메소드 |
---|---|
루핑 | forEach() |
매칭 | allMatch(), anyMatch(), noneMatch() |
집계 | count(), max(), min(), average(), sum(), reduce() |
조사 | findFirst(), findAny() |
수집 | collect() |
stream.forEach(name -> System.out.println(name))
으로 되어있을 때void forEach(Comsumer<? super T> action)
: 스트림의 각 요소를 action으로 소비 boolean allMatch(Predicate<? super T> predicate) : 스트림의 모든 요소가 Predicate를 만족하면 true를 반환
boolean anyMatch(Predicate<? super T> predicate) : 스트림의 요소 중 하나라도 Predicate를 만족하면 true를 반환
boolean noneMatch(Predicate<? super T> predicate) : 스트림의 요소 중 하나라도 Predicate를 만족하지 않으면 true를 반환
Stream<String> st0 = Stream.of("abc","cde","efg");
System.out.println(st0.allMatch(s -> s.equals("abc"))); //false
st0 = Stream.of("abc","cde","efg");
System.out.println(st0.anyMatch(s -> s.equals("cde"))); //true
st0 = Stream.of("abc","cde","efg");
System.out.println(st0.noneMatch(s -> s.equals("abcde")));//true
Optional<T> findFirst()
: 스트림의 첫 요소 또는 empty Optional 객체를 반환Optional<T> findAny()
: 스트림의 아무 요소나 가지는 Optional 객체를 반환 (병렬 스트림일 때 사용한다.) int firstValue = Arrays.stream(new int[]{1,2,3,4,5})
.filter(n -> n%3 ==0)
.findFirst()
.getAsInt();
Optional<T> reduce(BinaryOperator<T> accumulator)
//accumulator를 수행하고 Optional<T> 타입 반환
T reduce(T identity, BinaryOperator<T> accumulator)
// identity를 초기값으로 하여, accumulator를 이용해 집계 연산
<U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner)
// combiner를 이용해 병렬 스트림 결합
인터페이스 | 리턴 타입 | 메소드 |
---|---|---|
Stream | Optional | reduce(BinaryOperator accumulator |
T | reduce(T identitiy, BianryOperator accmulator) | |
IntStream | OptionalInt | reduce(IntBinaryOperator op) |
int | reduce(int indentity, IntBinaryOperator op) | |
LongStream | OptionalLong | reduce(LongBinaryOperator op) |
long | reduce(long indentity, LongBinaryOperator op) | |
DoubleStream | OptionalDouble | reduce(DoubleBinaryOperator op) |
double | reduce(double indentitiy, DoubleBinaryOperator op) |
reduce(BinaryOperator accumulator)
reduce(T identitiy, BianryOperator accmulator)
매개변수
System.out.println(IntStream.range(0,10).reduce(0,(value1,value2)->value1+value2)); //sum()
// 1,2와 더한걸 3이랑 더하고 12 와 3을 더한걸 4 와 더함 .. 누적해서 더하는 것이다.
// identity가 사용이 되는 이유는 처음 identitiy와 1을 더한값과 2를계산하기위해서
// 0 [0,1,2,3,4,5,6,7,8,9] 0+0 =0 -> 0+1->1 1+2-> 3 과같은 연산 0~9까지 더한 연산
// sum()으로도 나타낼 수 있다 sum,min,max등등 도 reduce로 구현되어 있다
System.out.println(IntStream.range(0,10).reduce(Integer.MAX_VALUE,(value1,value2)->value1<value2? value1:value2));// min()
public static <T> Optional<T> of(T value)
: value가 null인 경우 NullPointerException을 발생시키는 Wrapping 메소드public static <T> Optional<T> ofNullable(T value)
: value가 null인 경우 empty()의 결과를 리턴하는 Wrapping 메소드public static <T> Optional<T> empty()
: 값이 비어있는 Optional 객체를 리턴public T get()
: Optional의 값을 리턴하며, null일 경우 NullPointerException 발생public void ifPresent(Consumer<? super T> consumer)
: Optional 값이 null이 아닐 경우 consumer를 이용해 소비한다, 값이 저장되어 있지 않을 경우 디폴트 값(매개변수가 디폴트 값이 된다)public T orElse(T other)
: Optional의 값이 null일 경우 other를 반환한다, 값이 저장되어 있을 경우 Consumer 에서 처리public T orElseGet(Supplier<? extends T> other)
: Optional의 값이 null일 경우 Supplier를 통해 공급받은 값을 반환한다.public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X
: Optional의 값이 null일 경우 exceptionSupplier에서 공급받은 예외를 throw double avg = list.stream()
.mapToInt(Integer::intValue)
.average()
.getAsDouble();
System.out.println(avg); //NotSuchElementException
// isPresent()
OptionalDouble optionalDouble = list.stream()
.mapToInt(Integer::intValue)
.average()
if (optionalDouble.isPresent()){
System.out.println("값이 있는 경우 : " + optionalDouble.getAsDouble());
}else{
System.out.println("방법 1-값이 없는 경우 : " + 0.0);
// orElse()
double avg = list.stream()
.mapToInt(Integer::intValue)
.average()
.orElse(0.0;
System.out.println("방법 2 : " + avg);
// ifPresent()
list.add(2);
list.add(4);
list.stream()
.mapToInt(Integer::intValue)
.average()
.ifPresent(i-> System.out.println("방법 3 : "+ i));
// 값이 없을 경우 false가 되서 종료가 된다. consumer로 했기 때문에 바로 값 출력
스트림에서 필요한 요소만 필터링해서 별도의 컬렉션으로 만든다
collect라는 메소드 사용 collect(Collector <T,A,R> collector)
collect가 요소를 어떤 컬렉션에 수집할 것인지를 결정한다.
collect()메소드
<R,A> R collect(Collector<? super T,A,R) collector)
: collector를 이용해 새로운 Collection R에 담아 반환정적 메소드
: toList(), toSet(), toCollection(), toMap(), toConcurrentMap()<R, A> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner)
Collector의 타입 파라미터
리턴 타입 | 메소드 | 설명 |
---|---|---|
Collector<T,?,Collection> | Collectors.toCollection{Supplier} | Supplier가 제공한 Collection에 저장 |
Collector<T,?,ConcurrentMap<K,U>> | Collectors.toConcurrentMap(...) | ConcurrentMap에 저장한다. |
Collector<T,?,List> | Collectors.toList() | List에 저장 |
Collector<T,?,Map<K,U>> | Collectors.toMap() | Map에 저장 |
Collecotr<T,?,Set> | Collectors.toSet() | Set에 저장 |
Collectors.toConcurrentMap(...) - 멀티쓰레드 환경에서 쓰레드의 안전한 concurrentmap을 만들어서 거기에 요소를 수집하는 Collector를 얻는다.
A가 ? 인 이유
String[] array = {"Java", "Is", "Fun", "Isn't", "It", "?"};
List<String> list = Arrays.stream(array)
.filter(s -> s.length() >= 3)
.collect(Collectors.toList()); // ArrayList
// .collect(Collectors.toCollection(LinkedList::new))
System.out.println(list.getClass().getName() + ":" + list);
Set<String> set = Arrays.stream(array)
.filter(s -> s.length() >= 3)
.collect(Collectors.toSet()); // HashSet
// .collect(Collectors.toCollection(HashSet::new))
System.out.println(set.getClass().getName() + ":" + set);
Map<String, Integer> map = Arrays.stream(array)
.filter(s -> s.length() >= 3)
.collect(Collectors.toMap(s -> s, String::length)); // HashMap
// .collect(Collectors.toCollection(s -> s, String::length, (oldVal, newVal) -> newVal, TreeMap::new))
System.out.println(map.getClass().getName() + map);
Collectors의 정적 메소드를 이용한 그룹화와 분리
partitioningBy는 어떤 기준으로 무더기로 나누는 것 (2가지 true or false)
groupingBy는 어떤 기준으로 여러개 묶어 내는 것 (여러개)
public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier)
: classifier를 key값으로, 해당하는 값의 목록을 List인 value로 가지는 Map으로 스트림을 수집하는 Collector를 반환
public static <T, K, A, D> Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream)
: List 대신 downstream collector로 수집public static <T> Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate)
: predicate 결과를 key로, 해당하는 값의 목록을 List value로 가지는 Map으로 스트림을 수집하는 Collector를 반환
public static <T, A, D> Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate, Collector<? super T, A, D> downstream))
: List 대신 downstream collector로 수집 String[] array = {"Java", "Is", "Fun", "Isn't", "It", "?"};
Map<Character, List<String>> map1 = Arrays.stream(array)
.collect(Collectors.groupingBy(s -> s.charAt(0)));
System.out.println(map1);
Map<Boolean, List<String>> map2 = Arrays.stream(array)
.collect(Collectors.partitioningBy(s -> s.length() >= 3));
System.out.println(map2);
집계를 위한 Collector
String[] array = {"Java", "Is", "Fun", "Isn't", "It", "?"};
Map<Character, Long> map = Arrays.stream(array)
.collect(Collectors.groupingBy(s -> s.charAt(0),
Collectors.counting()));
System.out.println(map);