[Java 8] 13. Stream API - Terminal Operation

seony·2023년 5월 5일

java8

목록 보기
13/16

joining()

  • 스트림의 요소들을 String으로 합치는 역할을 한다.
  • 3 가지 버전이 있다.
    • 그냥 합치기
    • delimiter 지정
    • delimiter, prefix, suffix 지정
package com.learn.java.streams_terminal;

import com.learn.java.data.Student;
import com.learn.java.data.StudentDataBase;

import java.util.stream.Collectors;

public class StreamsJoiningExample {

    public static String joining_1() {
        return StudentDataBase.getAllStudents().stream()
                .map(Student::getName)
                .collect(Collectors.joining());
    }

    // delimiter를 지정해줄 수 있음
    public static String joining_2() {
        return StudentDataBase.getAllStudents().stream()
                .map(Student::getName)
                .collect(Collectors.joining(", "));
    }

    public static String joining_3() {
        return StudentDataBase.getAllStudents().stream()
                .map(Student::getName)
                .collect(Collectors.joining(", ", "(", ")"));
    }

    // prefix와 suffix를 지정해줄 수 있음
    public static void main(String[] args) {
        System.out.println("joining_1 : " + joining_1());
        System.out.println("joining_2 : " + joining_2());
        System.out.println("joining_3 : " + joining_3());

    }
}

결과

joining_1 : AdamJennyEmilyDaveSophiaJames
joining_2 : Adam, Jenny, Emily, Dave, Sophia, James
joining_3 : (Adam, Jenny, Emily, Dave, Sophia, James)

아래부터는 Collectors를 static import 해서 사용한다.

counting()

  • 총 몇 개의 elements 가 있는지 알려준다.
package com.learn.java.streams_terminal;

import com.learn.java.data.StudentDataBase;

import java.util.stream.Collectors;

import static java.util.stream.Collectors.counting;

public class StreamsCountingExample {

    public static long count() {
        return StudentDataBase.getAllStudents()
                .stream()
                .filter(student -> student.getGpa() >= 3.9)
                .collect(counting());
    }

    public static void main(String[] args) {
        System.out.println(count());
        
    }
}

mapping()

  • map() 중간 연산을 사용하지 않고 한 줄로 한 번에 동일한 연산을 할 수 있음
package com.learn.java.streams_terminal;

import com.learn.java.data.Student;
import com.learn.java.data.StudentDataBase;

import java.util.List;
import java.util.Set;

import static java.util.stream.Collectors.*;

public class StreamsMappingExample {
    public static void main(String[] args) {

        // mapping()을 사용하여 List로
        List<String> namesList = StudentDataBase.getAllStudents()
                .stream()
                .collect(mapping(Student::getName, toList()));

        System.out.println("namesList : " + namesList);

        // mapping()을 사용하여 Set 으로
        Set<String> namesSet = StudentDataBase.getAllStudents().stream()
                .collect(mapping(Student::getName, toSet()));

        System.out.println("namesSet : " + namesSet);

        // 기존 map() 사용한 경우
        StudentDataBase.getAllStudents().stream()
                .map(Student::getName)
                .collect(toList());


    }
}

결과

namesList : [Adam, Jenny, Emily, Dave, Sophia, James]
namesSet : [Adam, Emily, James, Jenny, Dave, Sophia]

minBy(), maxBy()

  • 각각 최솟값, 최댓값을 찾아준다.
    • 해당하는 값이 없을 수도 있기 때문에 Optional을 return 한다.
  • minBy, maxBy 모두 비교 기준이 필요하기 때문에 Comparator를 파라미터로 받는다.
package com.learn.java.streams_terminal;

import com.learn.java.data.Student;
import com.learn.java.data.StudentDataBase;

import java.util.Comparator;
import java.util.Optional;

import static java.util.stream.Collectors.maxBy;
import static java.util.stream.Collectors.minBy;

public class StreamsMinByMaxByExample {

    // gpa가 가장 낮은 학생
    public static Optional<Student> minBy_example() {
        return StudentDataBase.getAllStudents().stream()
                .collect(minBy(Comparator.comparing(Student::getGpa)));
    }

    // gpa가 가장 높은 학생
    public static Optional<Student> maxBy_example() {
        return StudentDataBase.getAllStudents().stream()
                .collect(maxBy(Comparator.comparing(Student::getGpa)));
    }

    public static void main(String[] args) {
        System.out.println(minBy_example().get());
        System.out.println(maxBy_example().get());
    }
}

결과

Student{name='Sophia', gradeLevel=4, gpa=3.5, gender='female', activities=[swimming, dancing, football]}
Student{name='Emily', gradeLevel=3, gpa=4.0, gender='female', activities=[swimming, gymnastics, aerobics]}

summingInt(), averagingInt()

  • 이름 그대로 int 값의 합과 평균 값을 구해준다.
package com.learn.java.streams_terminal;

import com.learn.java.data.Student;
import com.learn.java.data.StudentDataBase;

import java.util.stream.Collectors;

import static java.util.stream.Collectors.averagingInt;
import static java.util.stream.Collectors.summingInt;

public class StreamsSumAvgExample {

    // int 값 합 구하기
    public static int sum() {
        return StudentDataBase.getAllStudents().stream()
                .collect(summingInt(Student::getNoteBooks));
    }

    // int 값 평균 구하기
    public static double average() {
        return StudentDataBase.getAllStudents().stream()
                .collect(averagingInt(Student::getNoteBooks));
    }

    public static void main(String[] args) {

        System.out.println("Total No of notebooks : " + sum());
        System.out.println("Average No of notebooks : " + average());

    }
}

groupingBy()

  • SQL의 groupBy와 동일한 기능을 제공한다.
  • groupingBy()의 output은Map<K, V> 이다.
  • 3가지 버전의 groupingBy가 있다.
    1. groupingBy(classifier)
    2. groupingBy(classifier, downstream)
    3. groupingBy(classifier, supplier, downstream)
package com.learn.java.streams_terminal;

import com.learn.java.data.Student;
import com.learn.java.data.StudentDataBase;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static java.util.stream.Collectors.*;

public class StreamGroupingByExample {

    // 파라미터 1개
    public static void groupStudentByGender() {
        Map<String, List<Student>> studentMap = StudentDataBase.getAllStudents().stream()
                .collect(groupingBy(Student::getGender));

        System.out.println(studentMap);
    }

    // 파라미터 1개 커스텀
    // gpa >= 3.8 : outstanding
    // gpa < 3.8  : average
    public static void customizedGroupingBy() {
        Map<String, List<Student>> studentMap = StudentDataBase.getAllStudents().stream()
                .collect(groupingBy(student -> student.getGpa() >= 3.8 ? "OUTSTANDING" : "AVERAGE"));

        System.out.println(studentMap);
    }

    // 파라미터 2개 사용, value 값도 groupingBy 사용
    // key 값을 무엇으로 할지, value 값을 무엇으로 할지
    public static void twoLevelGrouping_1() {
        Map<Integer, Map<String, List<Student>>> studentMap = StudentDataBase.getAllStudents()
                .stream()
                .collect(groupingBy(Student::getGradeLevel,
                        groupingBy(student -> student.getGpa() >= 3.8 ? "OUTSTANDING" : "AVERAGE")));

        System.out.println(studentMap);
    }

    // 파라미터 2개 사용, value 값은 summingInt 사용
    // key 값을 무엇으로 할지, value 값을 무엇으로 할지
    public static void twoLevelGrouping_2() {
        Map<Integer, Integer> studentMap = StudentDataBase.getAllStudents()
                .stream()
                .collect(groupingBy(Student::getGradeLevel, summingInt(Student::getNoteBooks)));

        System.out.println(studentMap);
    }

    // 파라미터 3개
    // key 값, mapFactory(어떤 map 으로), value 형식
    public static void threeArgumentGroupBy() {
        LinkedHashMap<String, Set<Student>> studentMap = StudentDataBase.getAllStudents().stream()
                .collect(groupingBy(Student::getName, LinkedHashMap::new, toSet()));

        System.out.println(studentMap);
    }

    public static void main(String[] args) {
        groupStudentByGender();
        customizedGroupingBy();
        twoLevelGrouping_1();
        twoLevelGrouping_2();
        threeArgumentGroupBy();
    }
}

파라미터 2개 사용, value 값은 summingInt 사용 결과

{2=21, 3=27, 4=32}

partitioningBy()

  • partitioningBy()groupingBy()와 비슷하다.
  • 대신 Predicate를 input으로 받는다는 차이점이 있다.
  • Map<K, V>를 return 한다.
  • 2가지 버전이 있다.
    1. partitioningBy(predicate)
    2. partitioningBy(predciate, downstream) // downstream -> could be of any collector
package com.learn.java.streams_terminal;

import com.learn.java.data.Student;
import com.learn.java.data.StudentDataBase;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;

import static java.util.stream.Collectors.partitioningBy;
import static java.util.stream.Collectors.toSet;

public class StreamsPartitioningByExample {

	// 파라마터 1개
    public static void partitioningBy_1() {

        Predicate<Student> gpaPredicate = student -> student.getGpa() >= 3.8;
        Map<Boolean, List<Student>> paritioningMap = StudentDataBase.getAllStudents()
                .stream()
                .collect(partitioningBy(gpaPredicate));

        System.out.println("partitioningMap : " + paritioningMap);
    }

    // 파라미터 2개
    // predciate와, value 형식 정하기
    public static void partitioningBy_2() {

        Predicate<Student> gpaPredicate = student -> student.getGpa() >= 3.8;
        Map<Boolean, Set<Student>> paritioningMap = StudentDataBase.getAllStudents()
                .stream()
                .collect(partitioningBy(gpaPredicate, toSet()));

        System.out.println("partitioningMap2 : " + paritioningMap);
    }

    public static void main(String[] args) {
        partitioningBy_1();
        partitioningBy_2();
    }
}

0개의 댓글