반응형

[자바의 정석 - 기초편] ch14-15,16 스트림, 스트림의 특징

https://youtu.be/7Kyf4mMjbTQ

스트림

다양한 데이터 소스(컬렉션, 배열 등) 를 표준화된 방법으로 다루기 위한 것

컬렉션 프레임워크: 컬렉션(List, Set, Map, ...)들을 표준화된 방법으로 다루기 위해 정리했지만 실패함. List, Set, Map의 성격이 달라서 사용방법도 다름

JDK 1.8부터 스트림이 등장하면서 통일됨

 

중간 연산: 연산 결과가 스트림. 반복적으로 적용 가능

최종 연산: 연산 결과가 스트림이 아님. 단 한 번만 적용 가능 (스트림의 요소를 소모)

 

스트림으로 변환(생성)

1
2
3
4
5
6
7
8
9
10
List<Integer> list = Arrays.asList(1,2,3,4,5);
Stream<Integer> intStream = list.stream();
 
Stream<String> strStream = Stream.of(new String[]{"a""b""c"});
 
Stream<Integer> evenStream = Stream.iterator(0, n -> n+2);
 
Stream<Double> randomStream = Stream.generate(Math::random);
 
IntStream intStream = new Random().ints(5);
cs

 

예제

1
2
3
4
5
6
stream
   .distinct()                      // 중간 연산
    .limit(5)                        // 중간 연산
    .sorted()                        // 중간 연산
    .forEach(System.out::println)    // 최종 연산
 
cs

 

끊어서 사용 가능

1
2
3
4
5
6
7
8
9
10
String[] strArr = {"dd""aaa""CC""cc""b"};
 
Stream<String> stream = Stream.of(strArr);                // stream 생성
 
Stream<String> filteredStream     = stream.filter();        // 중간 연산
Stream<String> distinctedStream = stream.distinct();
Stream<String> sortedStream     = stream.sort();
Stream<String> limitedStream     = stream.limit(5);
 
int total = stream.count();                                 // 최종 연산
cs

 

스트림의 특징

1. 데이터 소스를 읽기만 할 뿐, 변경하지 않는다.

1
2
3
4
5
6
7
8
List<Integer> list = Arrays.asList(31542);
 
List<Integer> sortedList = list.stream()
                                .sorted()
                                .collect(Collectors.toList());
 
System.out.println(list);            // 3, 1, 5, 4, 2
System.out.println(sortedList);        // 1, 2, 3, 4, 5
cs

2. Iterator처럼 일회용 (필요하면 다시 스트림 생성해야 함)

1
2
strStream.forEach(System.out::println);
int numOfStr = strStream.count();        // 에러 -> 스트림이 이미 
cs

3. 지연 연산: 최종 연산 전가지 중산 연산이 수행되지 않음.

1
2
3
IntStream intStream = new Random().ints(146);
intStream.distinct().limit(5).sorted()              // 무한 스트림이지만 distinct() 
    .forEach(System.out::println)                    // 최종 연산
cs

4. 작업을 내부 반복으로 처리

1
2
3
4
5
for(String str : strList)
    System.out.println(str);
 
// 위와 동일
stream.forEach(System.out::println);
cs

 

5. 병렬 스트림: 스트림의 작업을 병렬로 처리 (멀티 쓰레드)

1
2
3
4
5
Stream<String> strStream = Stream.of("dd""aaa""CC""cc""b");
int sum = strStream
            .parallel()                    // 병렬 스트림으로 전환
            .mapToInt(s -> s.length())    // 문자열 길이 계산
            .sum();                        // 모든 문자열 길이의 합

cs

6. 기본형 스트림: IntStream, LongStream, DoubleStream

- 오토박싱, 언박싱의 비효율 제거 (Stream<Integer> 대신 IntStream 사용)

- 숫자와 관련된 유용한 메서드를 Stream<T>보다 더 많이 제공 (sum(), average() 등)

 

오토박싱: 1 (기본형) -> new Integer(1) (참조형)

언박싱   : new Integer(1) (참조형) -> 1 (기본형)

[자바의 정석 - 기초편] ch14-17~22 스트림만들기

https://youtu.be/AOw4cCVUJC4

컬렉션으로 스트림 생성

Collection 인터페이스의 stream()으로 컬렉션을 스트림으로 변환

 

Stream<E> stream()

예제

1
2
3
4
5
List<Integer>    list = Arrays.asList(1,2,3,4,5);
Stream<Integer> intStream = list.stream();
 
intStream.forEach(System.out::print);    // 정상 출력
intStream.forEach(System.out::print);    // 에러, 스트림이 이미 닫힘
cs

배열로 스트림 생성

1
2
3
4
5
Stream<String> strStream = Stream.of("a""b""c");
Stream<String> strStream = Stream.of(new String[]{"a""b""c"});
 
Stream<String> strStream = Arrays.stream(new String[]{"a""b""c"});
Stream<String> strStream = Arrays.stream(new String[]{"a""b""c"}, 03);
cs

난수를 요소로 갖는 스트림 생성

1
2
3
4
5
6
7
8
IntStream intStream = new Random().ints();
intStream
    .limit(5)
    .forEach(System.out::println);
 
// 위와 동일
IntStream intStream = new Random().ints(5);
                        .forEach(System.out::println);
cs

특정 범위의 정수를 요소로 갖는 스트림 생성(IntStream, LongStream)

1
2
IntStream intStream = IntStream.range(15);
IntStream intStream = IntStream.rangeClosed(15);
cs

 

람다식을 소스로 하는 스트림 생성

1
2
static <T> Stream<T> iterate(T seed, UnaryOperator<T> f);    // 이전 요소에 종속적
static <T> Stream<T> generate(Supplier<T> s);                // 이전 소에 독립적
cs

예제

1
2
3
4
Stream<Integer> evenStream = Stream.iterate(0, n -> n+2);    // 0, 2, 4, 6, ...
 
Stream<Double>    randomStream    = Stream.generate(Math::random);
Stream<Integer>    oneStream        = Stream.generate( () -> 1);
cs

파일을 소스로 하는 스트림 생성

1
2
3
4
5
Stream<Path> Files.list(Path dir);    // dir에 있는 파일 또는 디렉토리
 
Stream<String> Files.lines(Path path);    // 파일 내용을 라인 단위로 읽어서 String으로 변환
Stream<String> Files.lines(Path path, Charset cs);
Stream<String> lines();
cs

빈 스트림 생성

1
Stream emptyStream = Stream.empty();
cs

[자바의 정석 - 기초편] ch14-23~25 스트림의 연산

https://youtu.be/iY8ta9upajE

중간 연산

최종 연산

[자바의 정석 - 기초편] ch14-26~29 스트림의 중간연산(1)

https://youtu.be/G2lPQB42GL8

 

filter()

1
2
3
4
5
6
7
8
9
10
11
IntStream intStream = IntStream.rangeClosed(110);    // 1 ~ 10
 
intStream
    .filter(i -> i%2 != 0 && i%3 != 0)
    .forEach(System.out::print);
 
// 위와 동일
intStream
    .filter(i -> i%2 != 0)
    .filter(i -> i%3 != 0)
    .forEach(System.out::print);
cs

문자열 스트림 정렬 방법

Comparator의 comparing()으로 정렬 기준 제공

1
2
3
4
5
studentStream
    .sorted(Comparator.comparing(Student::getBan))            // 반 별로 정렬
                    .thenComparing(Student::getTotalScore)    // 총점 별로 정렬
                    .thenComparing(Student::getName))        // 이름 별로 정렬
    .forEach(System.out::println);
cs

[자바의 정석 - 기초편] ch14-30~34 스트림의 중간연산(2)

https://youtu.be/sEa4RQGG0HU

map(): 스트림의 요소 변환

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Stream<File> fileStream = Stream.of(
                            new File("Ex1.java"),
                            new File("Ex1"),
                            new File("Ex1.bak"),
                            new File("Ex2.java"),
                            new File("Ex1.txt"));
 
fileStream
   .map(File::getName)                           // Stream<File> -> Stream<String>
    .filter(s -> s.indexOf('.'!= -1)            // 확장자 없는 것 제외
    .map(s -> s.substring(s.indexOf('.'+ 1)    // 확장자(. 뒤) 추출
    .map(String::toUpperCase)                    // 대문자로 변환
   .distinct()                                   // 중복 제거
    .forEach(System.out::print);
        
cs

peek(): 스트림의 요소를 소비하지 않고 읽기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Stream<File> fileStream = Stream.of(
                            new File("Ex1.java"),
                            new File("Ex1"),
                            new File("Ex1.bak"),
                            new File("Ex2.java"),
                            new File("Ex1.txt"));
 
fileStream
    .map(File::getName)                                        // 파일명 반환
    .filter(s -> s.indexOf('.'!= -1)                        // 확장자 없는 것 제외
    .peek(s -> System.out.printf("filename = %s%n", s))        // 파일명 출력
    .map(s -> s.substring(s.indexOf('.'+ 1)                // 확장자(. 뒤) 추출
    .peek(s -> System.out.printf("extension = %s%n", s))    // 확장자출력
    .map(String::toUpperCase)                                // 대문자로 변환
    .distinct()                                                // 중복 제거
    .forEach(System.out::print);                            // 최종 연산 스트림 소비
        
cs

flatMap(): 스트림의 스트림(Stream<Stream<T> >)을 스트림(Stream<T>)로 변환

1
2
3
4
5
6
7
8
9
10
Stream<String[]> strArrStrm = Stream.of(new String[]{"abc""def""ghi"},
                                         new String[]("ABC""GHI""JKLMN"});
 
// 1. map()
Stream<Stream<String> > strStrStrm = strArrStrm.map(Arrays::stream);
 
// 2. flatMap()
Stream<String> strStrStrm = strArrStrm.flatMap(Arrays::stream);
 
 
cs

예제 1

1
2
3
4
5
6
7
8
9
Stream<String[]> strArrStrm = Stream.of(new String[]{"abc""def""ghi"},
                                         new String[]("ABC""GHI""JKLMN"});
Stream<String> strStrm = strArrStrm.flatMap(Arrays::stream);
 
strStrm
    .map(String::toLowerCase)
    .distinct()
    .sorted()
    .forEach(System.out::println);
cs

예제 2

1
2
3
4
5
6
7
8
9
10
11
String[] lineArr = {
    "Believe or not It is true",
    "Do or do not There is no try",
};
Stream<String> lineStream = Arrays.stream(lineArr);
lineStream
    .flatMap(line -> Stream.of(line.split(" +")))    // 정규표현식, 공백 1개 이상
    .map(String::toLowerCase)
    .distinct()
    .sorted()
    .forEach(System.out::println);
cs

[자바의 정석 - 기초편] ch14-35~39 Optional에 대한 강의입니다.

https://youtu.be/W_kPjiTF9RI

Optional<T>

T 타입 객체의 래퍼 클래스

1
2
3
4
public final clas Optional<T> {
    private final T value;    // T타입의 참조변수
    ...
}
cs

null을 Optional<>에 담아서 반환

return null;

=> return Optional<null>;

 

Optional<T> 객체 생성 방법

1
2
3
4
5
String str = "abc";
Optional<String> optVal = Optional.of(str);
Optional<String> optVal = Optional.of("abc");
Optional<String> optVal = Optional.of(null);            // NPE 발생
Optional<String> optVal = Optional.ofNullable(null);    // OK
cs

null 대신 빈 Optional<T> 객체 사용

1
2
3
Optional<String> optVal = null;                // 바람직하지 않음
Optional<String> optVal = Optional.empty();    // 빈 객체로 초기화
 
cs

Optional 객체의 값 가져오기: get(), orElse(), orElseGet(), orElseThrow()

1
2
3
4
5
6
Optional<String> optVal = Optional.of("abc");
 
String str1 = optVal.get();                                        // null이면 예외 발생
String str2 = optVal.orElse("");                                // null이면 "" 반환
String str3 = optVal.orElseGet(String::new);                    // 람다식 사용 가능 () -> new String()
String str4 = optVal.orElseThrow(NullPointerException::new)        // null이면 예외 발생 (예외 지정 가능)
cs

 

isPresent(): Optional 객체의 값이 null이면 false, 아니면 true 반환

1
2
3
if(Optional.ofNullable(str).isPresent()) {    // if (str != null) 
    System.out.println(str);
}
cs

기본형을 감싸는 래퍼 클래스: OptionalInt, OptionalLong, OptionalDouble

일반 Optional<T>보다 성능 좋음

 

OptionalInt의 값 가져오기

빈 Optional 객체와의 비교

1
2
3
4
5
6
OptionalInt opt = OptionalInt.of(0);    // 0 저장
OptionalInt op2 = OptionalInt.empty();    // 초기값 0이지만 실제로는 값이 없음
 
opt.isPresent()  -> true
opt2.isPresent() -> false
opt.equals(opt2) -> false
cs

예제 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Optional<String> optStr = Optional.of("abcde");
Optional<Integer> optInt = optStr.map(String::length); // .map(s -> s.length());
 
int result1 = Optional.of("123")
                    .filter(x -> x.length() > 0)
                    .map(Integer::parseInt)
                    .get();
 
int result2 = Optional.of("")
                    .filter(x -> x.length() > 0)
                    .map(Integer::parseInt)
                    .orElse(-1);
 
Optional.of("456")
        .map(Integer::parseInt)
        .ifPresent(x -> System.out.printf("result3 = %d%n", x);
cs

예제 2

1
2
3
4
5
OptionalInt optInt1 = OptionalInt.of(0);
OptionalInt optInt2 = OptionalInt.empty();
 
System.out.println(optInt1.getAsInt());    // 0
System.out.println(optInt2.getAsInt());    // NoSuchElementException
cs

 

[자바의 정석 - 기초편] ch14-40~44 스트림의 최종연산에 대한 강의입니다.

https://youtu.be/M_4a4tUCSPU

forEach(), forEachOrdered(): 스트림의 모든 요소에 지정된 작업 수행

1
2
3
4
5
6
7
8
void    forEach(Comsumer<super T> action)            // 병렬 스트림인 경우 순서 보장 X
void    forEachOrdered(Consumer<super T> action)     // 병렬 스트림인 경우 순서 보장 O
 
IntStream.range(110).sequential().forEach(System.out::print);
IntStream.range(110).sequential().forEachOrdered(System.out::print);
 
IntStream.range(110).parallel().forEach(System.out::print); // 순서 보장 X
IntStream.range(110).parallel().forEachOrdered(System.out::print); // 순서 보장 O
cs
 
 
 

allMatch(), anyMatch(), noneMatch(): 조건 검사

1
2
3
4
5
6
boolean allMatch  (Predicate<super T> predicate)
boolean anyMatch  (Predicate<super T> predicate)
boolean noneMatch (Predicate<super T> predicate)
 
boolean hasFailedStu = stuStream
                            .anyMatch(s -> s.getTotalScore() <= 100);
cs

findFirst(), findAny(): 조건에 일치하는 요소 찾기

1
2
3
4
5
6
7
8
9
10
Optional<T> findFirst();
Optional<T> findAny();
 
Optional<Student> result = stuStream
                                .filter(s -> s.getTotalScore() <= 100)
                                .findFirst();
 
Optional<Student> result = parallelStream
                                .filter(s -> s.getTotalScore() <= 100)
                               .findAny();
cs

reduce(): 스트림의 요소를 하나씩 줄여가며 누적연산 수행

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Optional<T> reduce (BinaryOperator<T> accumulator);
T            reduce (T identity, BinaryOperator<T> accumulator);
U            reduce (T identity, BiFunction<U, T, U> accumulator, BinaryOperator<T> combiner);
 
* identity        : 초기값
* accumulator     : 이전 연산결과와 스트림의 요소에 수행할 연산 (누적해서 수행할 작업)
* combiner        : 병렬처리된 결과를 합치는데 사용할 연산 (병렬 스트림)
 
int count     = intStream.reduce(0, (a, b) -> a + 1);
/*
    int a = identity;
    for(int b : stream)
        a += 1;
*/
 
int sum        = intStream.reduce(0, (a, b) -> a + b);
/*
    int a = identity;
    for(int b : stream)
        a += b;
*/
 
int max        = intStream.reduce(Integer.MIN_VALUE, (a, b) -> a > b ? a : b);
int min        = intStream.reduce(Integer.MAX_VALUE), (a, b) -> a < b ? a : b);
cs

예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
String[] strArr = {
    "Inheritance""Java""Lambda""stream""OptionalDouble""IntStream""count""sum"
};
 
Stream
    .of(strArr)
    .forEach(System.out::println);
 
boolean noEmptyStr = Stream
                        .of(strArr)
                        .noneMatch(s -> s.length() == 0);
 
Optional<String> sWord = Stream
                            .of(strArr)
                            .filter(s -> s.charAt(0== 's')
                            .findFirst();
 
System.out.println("noEmptyStr = " + noEmptyStr);
System.out.println("sWord= " + sWord.get());
 
// Stream<String[]>을 IntStream으로 변환
IntStream intStream1 = Stream.of(strArr).mapToInt(String::length);
IntStream intStream2 = Stream.of(strArr).mapToInt(String::length);
IntStream intStream3 = Stream.of(strArr).mapToInt(String::length);
IntStream intStream4 = Stream.of(strArr).mapToInt(String::length);
 
int count = intStream1.reduce(0, (a,b) -> a + 1);
int sum   = intStream2.reduce(0, (a,b) -> a + b);
 
OptionalInt max = intStream3.reduce(Integer::max);
OptionalInt min = intStream4.reduce(Integer::min);
 
System.out.println("count = " + count);
System.out.println("sum = " + sum);
System.out.println("max = " + max.getAsInt());
System.out.println("min = " + min.getAsInt());
cs

[자바의 정석 - 기초편] ch14-45~49 collect()와 Collectors에 대한 강의입니다.

https://youtu.be/u9KOajCP3D8

collect(): Collector를 매개변수로 하는 스트림의 최종 연산

            그룹별 리듀싱

1
2
Object collect(Collector collector);
Object collect(Supplier supplier, Biconsumer accumulator, Biconsumer combiner);    // 잘 안씀
cs

Collector: 수집(collect)에 필요한 메서즈를 정의해 놓은 인터페이스

1
2
3
4
5
6
7
8
public interface Collector<T, A, R> {    // T(요소)를 A에 누적한 다음, 결과를 R로 변환해서 반환
    Supplier<A>             supplier();        // StringBuilder::new               누적할 곳
    BiConsumer<A, T>        accumulator();        // (sb, s) -> sb.append(s)          누적해서 수행할 작업
    BinaryOperator<A>       combiner();          // (sb1, sb2) -> sb1.append(sb2)    결합 방법 (병렬)
    Function<A, R>          finisher();         // ab -> ab.toString()              최종 변환
    Set<Characteristics>    characteristics();    // 컬렉터의 특성이 담긴 Set을 반환
    ...
}
cs

Collectors 클래스는 다양한 기능의 컬렉터(Collector를 구현한 클래스)를 제공

* 변환: mapping(), toList(), toSet(), toMap(), toCollection(), ...

* 통계: counting(), summingInt(), averageInt(), maxBy(), minBy(), summarizingInt(), ...

* 문자열 결합: joining()

* 리듀싱: reducing()

* 그룹화와 분할: groupingBy(), partitioningBy(), collectingAndThen()

 

collect(): 최종 연산

Collector: 인터페이스

Collectors: Collector를 구현한 클래스

 

스트림을 컬렉션으로 변환: toList(), toSet(), toMap(), toCollection()

1
2
3
4
5
6
7
8
9
10
List<String> names = stuStream                                //    Stream<Student>
                            .map(Student::getName)            // -> Stream<String>
                            .collect(Collectors.toList());    // -> List<String>
 
ArrayList<String> list = names                                                    //   List<String>
                            .stream()                                            //   Stream<String>
                            .collect(Collectors.toCollection(ArrayList::new));    //-> ArrayList<String>
 
Map<String, Person> map = personStream                                                //    Stream<Person>.
                            .collect(Collectors.toMap(p -> p.getRegId(), p -> p));  // -> Map<String, Person>
cs

스트림을 배열로 변환: toArray()

1
2
3
Student[] stuNames = studentStream.toAray(Student[]::new);
Object[]  stuNames = studentStream.toAray();    // 매개변수 없으면 Object[]
Student[] stuNames = studentStream.toAray();    // ERROR
cs

스트림의 통계정보 제공: counting(), summingInt(), maxBy(), minBy()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
long count = stuStream.count();
 
// 위와 동일
long count = stuStream.collect(counting());
 
 
long totalScore = stuStream
                        .mapToInt(Student::getTotalScore)
                        .sum();
// 위와 동일
long totalScore = stuStream
                        .collect(summingInt(Student::getTotalScore));
 
 
OptionalInt topScore = studentStream
                                .mapToInt(Student::getTotalScore)
                                .max();
 
Optional<Student> topStudent = stuStream
                                    .max(Comparator.comparingInt(Student::getTotalScore));
// 위와 동일
Optional<Student> topStudent = stuStream
                                    .collect(maxBy(Comparator.comparingInt(Student::getTotalScore)));
cs

스트림을 리듀싱: reducing()

1
2
3
Collector reducing(BinaryOperator<T> op)
Collector reducing(T identity, BinaryOperator<T> op)
Collector reducing(U identity, Function<T, U> mapper, BinaryOperator<T> op)
cs

예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
IntStream intStream = new Random()
                            .ints(146)
                            .distinct()
                            .limit(6);
 
OptionalInt             max = intStream.reduce(Integer::max);
OptionalInt<Integer> max = intStream.boxed()
                                    .collect(reducing(Integer::max));
 
long sum = intStream.reduce(0, (a,b) -> a+b);
long sum = intStream.boxed()
                    .collect(reducing(0, (a,b) -> a+b));
 
int grandTotal = stuStream.map(Student::getTotalScore)
                          .reduce(0, Integer::sum);
int grandTotal = stuStream.collect(reducing(0, Student::getTotalScore, Integer::sum));
cs

문자열 스트림의 요소를 모두 연결: joining()

1
2
3
4
String studentNames = stuStream.map(Student::getName).collect(joining());                // ABC
String studentNames = stuStream.map(Student::getName).collect(joining(", "));            // A, B, C
String studentNames = stuStream.map(Student::getName).collect(joining(", ""[""]"));  // [A, B, C]
String studentInfo = stuStream.collect(joining(", "));    // Student의 toString()으로 결합
cs

[자바의 정석 - 기초편] ch14-50~55 스트림의 그룹화와 분할에 대한 강의입니다.

https://youtu.be/VUh_t_j9qjE

partitioningBy(): 스트림을 2분할 (예제: https://github.com/castello/javajungsuk3/blob/master/source/ch14/StreamEx7.java)

 

groupingBy(): 스트림을 n분할 (예제: https://github.com/castello/javajungsuk3/blob/master/source/ch14/StreamEx8.java)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Map<Boolean, List<Student> > stuBySex = stuStream
                                            .collect(partitioningBy(Student::isMale)); // 학생들을 성별로 분할
List<Student> maleStudent   = stuBySex.get(true);    // 남자: true
List<Student> femaleStudent = stuBySex.get(false);    // 여자: false
 
 
 
Map<Boolean, Long> stuNumBySex = stuStream
                                       .collect(partitioningBy(Student::isMale,
                                                               counting())); // 분할 + 통계
int maleStudentNum   = stuNumBySex.get(true);    // 남자: true
int femaleStudentNum = stuNumBySex.get(false);    // 여자: false
 
 
 
Map<Boolean, Optional<Student> > topScoreBySex = stuStream
                                                    .collect(partitioningBy(Student::isMale, 
                                                                                 maxBy(comparingInt(Student::getScore))); // 분할 + 통계
int maleTopScoreBySex   = topScoreBySex.get(true);    // 남자: true
int femaleTopScoreBySex = topScoreBySex.get(false);    // 여자: false
 
 
 
Map<Boolean, Map<Boolean, List<Student> > > failedStuBySex = stuStream
                                                    .collect(partitioningBy(Student::isMale,
                                                                                 partitioningBy(s -> s.getScore() < 150))); // 다중 분할
List<Student> failedMaleStudent   = failedStuBySex.get(true);    // 남자: true
List<Student> failedFemaleStudent = failedStuBySex.get(false);    // 여자: false
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Map<Integer, List<Student> > stuByBan = stuStream
                                            .collect(groupingBy(Student::getBan, toList()));
 
 
 
Map<Integer, Map<Integer, List<Student> > > stuByHakAndBan = stuStream
                                                                .collect(groupingBy(Student::getHak, // 1. 학년 별 그룹화
                                                                         groupingBy(Student::getBan) // 2. 반 별 그룹화
                                                                ));
 
 
Map<Integer, Map<Integer, Set<Student.Level> > > stuByHakAndBan = stuStream
                                                                        .collect(
                                                                                groupingBy(Student::getHak,
                                                                                groupingBy(Student::getBan,
                                                                                mapping(s -> {
                                                                                                if        (s.getScore() >= 200return Student.Level.HIGH;
                                                                                                else if    (s.getScore() >= 100return Student.Level.MID;
                                                                                                else                          return Student.Level.LOW;
                                                                                }, toSet())))
                                                                        );
                                                                                
cs
반응형

+ Recent posts