Skip to content

스트림의 최종 연산 #44

Description

@korjun1993

스트림의 최종 연산

  • forEach
void forEach(Consumer<? super T> action)
  • 조건 검사
boolean allMatch(Predicate<? super T> predicate)
boolean anyMatch(Predicate<? super T> predicate)
boolean noneMatch(Predicate<? super T> predicate)
  • 필터링 결과 가져오기
// 조건에 일치하는 첫 번째 것을 반환한다.
stuStream.filter(s->s.getTotalScore() <= 100).findFirst();

// 병렬 스트림인 경우에는 findFirst 대신 findAny를 사용해야 한다.
stuStream.parallel().filter(s->s.getTotalScore() <= 100).findAny();
  • 통계
    IntStream과 같은 기본형 스트림에는 스트림의 요소들에 대한 통계 정보를 얻을 수 있는 메서드들이 있다. 그러나 기본형 스트림이 아닌 경우에는 통계와 관련된 메서드들이 아래의 3개뿐이다.
long count();
Optional<T> max(Comparator<? super T> comparator)
Optional<T> min(Comparator<? super T> comparator)
  • 리듀싱
    스트림의 요소를 줄여나가면서 연산을 수행하고 최종결과를 반환한다. 처음 두 요소를 가지고 연산한 결과를 가지고 그 다음 요소와 연산한다.
T reduce(T identity, BinaryOperator<T> accumulator) // identity: 초기값
U reduce(U identity, BiFunction<U, T, U> accumulator, BinaryOperator<U> combiner)

// 예시
int count = intStream.reduce(0, (a, b) -> a + 1); // count()
int sum = intStream.reduce(0, (a,b) -> a + b); // sum()
int max = intStream.reduce(Integer.MIN_VALUE, (a,b) -> a>b ? a:b); // max()
int min = intStream.reduce(Integer.MAX_VALUE, (a,b) -> a<b ? a:b); // min()

// for문으로 sum()을 표현하면 다음과 같다.
int a = identity // 초기값을 a에 저장한다.
for (int b : stream) {
   a = a + b; // 모든 요소의 값을 a에 누적한다.
}

// 즉, 일반화하면 다음과 같다.
T reduce(T identity, BinaryOperator<T> accumulator) {
   T a = identity;
   for (T b : stream) {
      a = accumulator.apply(a, b);
   }
   return a;
}
  • collector

    • collect()가 스트림의 요소를 수집한다. 이 때 어떻게 수집할 것인가에 대한 방법을 정의한 것이 컬렉터(collector)이다.
    • 컬렉터는 Collector 인터페이스를 구현한 것으로, 직접 구현할 수도 있고 미리 작성된 것을 사용할 수도 있다.
    • Collectors 클래스는 미리 작성된 다양한 종류의 컬렉터를 반환하는 static 메서드를 가지고 있다.
  • 스트림 → 컬렉션

// Collectors 클래스의 toList()와 같은 메서드를 사용하면된다.
List<String> names = stuStream.map(Student::getName).collect(Collectors.toList());

// Map으로 바꾸려면 어떤 필드를 키, 값으로 사용할지 지정해줘야 한다.
Map<String, Person> map = personStream.collect(Collectors.toMap(p -> p.getRegId(), p->p));
  • 스트림 → 배열
// 스트림에 저장된 요소들을 T[] 타입의 배열로 변환하려면, toArray()를 사용하면 된다.
// 단, 해당 타입의 생성자 참조를 매개변수로 지정해줘야 한다. 그렇지 않으면 Object[] 가 반환된다.
Student[] stuNames = studentStream.toArray(Student[]::new);
Student[] stuNames = studentStream.toArray(); // 에러
Object[] stuNames = studentStream.toArray();
  • 문자열 스트림 → 문자열
String studentNames = stuStream.map(Student::getName).collect(Collectors.joining());
String studentNames = stuStream.map(Student::getName).collect(Collectors.joining(","));

// Student의 toString()으로 결합
String studentInfo = stuStream.collect(Collectors.joining(","));
  • 분할
    • 스트림의 지정된 조건에 일치하는 그룹과 일치하지 않는 그룹으로 분할한다.
Collector partitioningBy(Predicate predicate)
Collector partitioningBy(Predicate predicate, Collector downstream)

// 학생들을 성별로 분할
Map<Boolean, List<Student>> stuBySex = stuStream.collect(Collectors.partitioningBy(Student::isMale));

List<Student> maleStudent = stuBySex.get(true);
List<Student> femaleStudent = stuBySex.get(false);

// 성별 학생들의 수
Map<Boolean, Long>> stuNumBySex = stuStream.collect(Collectors.partitioningBy(Student::isMale, Collectors.counting()));

long maleNum = stuNumBySex.get(true);
long femaleNum = stuNumBySex.get(false);

// 성별로 성적이 150점이 아래인 학생
Map<Boolean, Map<Boolean, List<Student>>> failedStuBySex = Stream.of(stuArr)
			.collect(Collectors.partitioningBy(Student::isMale, Collectors.partitioningBy(s -> s.getScore() <= 100)));
  • 그룹화
    • 스트림의 요소를 특정 기준으로 그룹화한다.
Collector groupingBy(Function classifer)
Collector groupingBy(Function classifer, Collector downstream)
Collector groupingBy(Function classifer, Supplier mapFactory, Collector downstream)

// 예시
// 1. 그룹화(반별)
Map<Integer, List<Student>> stuByBan = Stream.of(stuArr).collect(Collectors.groupingBy(Student2::getBan));

// 2. 그룹화(성적별)
Map<Student2.Level, List<Student2>> stuByLevel = Stream.of(stuArr).collect(Collectors.groupingBy(s -> {
			if (s.getScore() >= 200) {
				return Student2.Level.HIGH;
			} else if (s.getScore() >= 100) {
				return Student2.Level.MID;
			} else {
				return Student2.Level.LOW;
			}
		}));

// 3. 그룹화 + 통계(성적별 학생수)
Map<Student2.Level, Long> stuCntByLevel = Stream.of(stuArr).collect(Collectors.groupingBy(s -> {
			if (s.getScore() >= 200) {
				return Student2.Level.HIGH;
			} else if (s.getScore() >= 100) {
				return Student2.Level.MID;
			} else {
				return Student2.Level.LOW;
			}
		}, Collectors.counting()));

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions