728x90
2023.01.30 - [JAVA/Java 기초] - Optional 클래스.java
Optional 클래스.java
Optional 클래스 java.util.Optional Optional은 선택형 값을 캡슐화 하는 클래스 입니다. 값이 있으면 Optional 클래스는 값을 감쌉니다. 값이 없으면 Optional.empty 메서드로 Optional을 반환 합니다. 값이 없을경
less-go.tistory.com
스트림이 제공하는 메소드
- 스트림은 기본 집계 메소드인 sum(), average(), count(), max(), min()을 제공하지만, 다양한 집계 결과물을 만들수 있도록 redeuce() 메소드도 제공합니다.

- 매개값인 BinaryOperator는 함수형 인터페이스 입니다.
- BinaryOperator는 두개의 매개값을 받아 하나의 값을 리턴하는 apply() 메소드를 가지고 있어, 다음과 같이 람다식을 작성할수 있습니다.
(a, b) -> { ... return 값;}
또는
(a, b) -> 값
//return 문만 있을 경우 중괄호와 return 키워드를 생략 가능합니다.
- reduce()는 스트림에 요소가 없을 경우 예외가 발생하지만, identify 매개값이 주어지면 이 값을 디폴트 값으로 리턴합니다.
int sum = stream
.reduce((a, b) -> a+b)
.getAsInt();
// 스트림에 요소가 없을경우 NoSuchElementException을 발생 시킵니다.
int sum = stream
.reduce(0, (a,b) -> a+b);
// 디폴트 값 (identity)인 0을 리턴합니다.
Student.java
public class Student{
private String name;
private int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
public String getName() {return name;}
public int getScore() {return score;}
}
ReductionExam.java
import java.util.Arrays;
import java.util.List;
public class ReductionExam {
public static void main(String[] args) {
List<Student> studentList = Arrays.asList(
new Student("홍길동", 92),
new Student("신용권", 95),
new Student("감자바", 88)
);
//방법 1
int sum1 = studentList.stream()
.mapToInt(Student :: getScore)
.sum();
//방법 2
int sum2 = studentList.stream()
.map(Student :: getScore)
.reduce(0, (a,b)-> a+b);
System.out.println("sum1: " + sum1);
System.out.println("sum2: " + sum2);
}
}
결과 :
sum1: 275
sum2: 275
필터링 한 요소 수집
- Stream의 collect(Collector<T,A,R> collector) 메소드는 필터링 또는 매핑된 요소들을 새로운 컬렉션에 수집하고, 이 컬렉션을 리턴합니다.
- 매개값인 Collector는 어떤 요소를 어떤 컬렉션에 수집할 것인지를 결정합니다.
- 타입 파라미터의 T는 요소, A는 누적기 accumulator, 그리고 R은 요소가 저장될 컬렉션

Student 스트림에서 남학생만 필터링해서 별도의 List로 생성하는 코드입니다.
List<Student> maleList = totalList.stream()
.filter(s->s.getSex().equals("남")) //남학생만 필터링
.collect(Collecotrs.toList());
Student 스트림에서 이름을 키로, 점수를 값으로 갖는 Map 컬렉션을 생성하는 코드입니다.
Map<String, Integer> map = totoalList.stream()
.collect(
Collectors.toMap(
s->s.getName(), //Student 객체에서 키가 될 부분 리턴
s->s.getScore() //Student 객체에서 값이 될 부분 리턴
)
);
Java 16부터 편리하게 요소 스트림에서 List 컬렉션을 얻는 방법 = 스트림에서 바로 toList() 메소드를 사용합니다.
List<Student> maleList = totalList.stream()
.filter(s->s.getSex().equals("남"))
.toList();
public class Student{
private String name;
private String sex;
private int score;
public Student(String name, String sex, int score) {
this.name = name;
this.sex = sex;
this.score = score;
}
public String getName() {return name;}
public String getSex() {return sex;}
public int getScore() {return score;}
}
import java.util.ArrayList;
import java.util.List;
import java.util.Map;import java.util.stream.Collector;
import java.util.stream.Collectors;
public class CollectExam {
public static void main(String[] args) {
List<Student> totalList = new ArrayList<>();
totalList.add(new Student("홍길동", "남", 92));
totalList.add(new Student("김수영", "여", 87));
totalList.add(new Student("감자바", "남", 95));
totalList.add(new Student("오해영", "여", 93));
//남학생만 묶어 List 생성
List<Student> maleList = totalList.stream()
.filter(s->s.getSex().equals("남"))
.collect(Collectors.toList());
// java 16버전 이후
// List<Student> maleList = totalList.stream()
// .filter(s->s.getSex().equals("남"))
// .toList();
maleList.stream()
.forEach(s -> System.out.println(s.getName()));
System.out.println();
//학생이름을 키, Student 객체를 값으로 갖는 Map 생성
Map<String, Integer> map = totalList.stream()
.collect(
Collectors.toMap(
s -> s.getName(),
s -> s.getScore()
)
);
System.out.println(map);
}
}
결과 :
홍길동
감자바
{오해영=93, 홍길동=92, 감자바=95, 김수영=87}
요소 그룹핑
- collectors.groupingBy() 메소드에서 얻은 Collector를 collect() 메소드를 호출할 때 제공합니다.
- groupingBy()는 Function을 이용하여 T를 K로 매핑하고, K를 키로해 List<T>를 값으로 갖는 Map 컬렉션을 생성합니다.

다음은 "남", "여"를 키로 설정하고 List<Student>를 값으로 갖는 Map 을 생성하는 코드입니다.
Map<String, List<Student>> map = totalList.stream()
.collect(
Collectors.groupingBy(s->s.getSex()) //그룹핑 키 리턴
);
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class CollectExam {
public static void main(String[] args) {
List<Student> totalList = new ArrayList<>();
totalList.add(new Student("홍길동", "남", 92));
totalList.add(new Student("김수영", "여", 87));
totalList.add(new Student("감자바", "남", 95));
totalList.add(new Student("오해영", "여", 93));
Map<String, List<Student>> map = totalList.stream()
.collect(
Collectors.groupingBy(s->s.getSex())
);
List<Student> maleList = map.get("남");
maleList.stream().forEach(s-> System.out.println(s.getName()));
System.out.println();
List<Student> femaleList = map.get("여");
femaleList.stream().forEach(s-> System.out.println(s.getName()));
}
}
결과:
홍길동
감자바
김수영
오해영
- Collectors.groupingBy() 메소드는 그룹핑 후 매핑 및 집계(평균, 카운팅, 연결, 최대, 최소, 합계)를 수행할 수 있도록 두 번째 매개값인 Collector를 가질 수 있습니다.

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class CollectExam {
public static void main(String[] args) {
List<Student> totalList = new ArrayList<>();
totalList.add(new Student("홍길동", "남", 92));
totalList.add(new Student("김수영", "여", 87));
totalList.add(new Student("감자바", "남", 95));
totalList.add(new Student("오해영", "여", 93));
Map<String, Double> map = totalList.stream()
.collect(
Collectors.groupingBy(
s->s.getSex(),
Collectors.averagingDouble(s->s.getScore())
)
);
System.out.println(map);
}
}
결과 :
{남=93.5, 여=90.0}
동시성과 병렬성
- 동시성 : 멀티 작업을 위해 멀티 스레드가 하나의 코어에서 번갈아 가며 실행하는 것
- 병렬성 : 멀티 작업을 위해 멀티 코어를 각각 이용해서 병렬로 실행하는 것

- 데이터 병렬성 : 전체 데이터를 분할해서 서브 데이터 셋으로 만들고 이 서브 데이터 셋들을 병렬 처리해서 작업을 빨리 끝내는 것
- 작업 병렬성 : 서로 다른 작업을 병렬 처리 하는 것
포크조인 프레임 워크
- 포크(Fork) 단계 : 전체요 소들을 서브 요소셋으로 분할하고, 각각의 서브 요소셋을 멀티 코어에서 병렬로 처리 합니다.
- 조인(Join) 단계 : 서브 결과를 결합해서 최종 결과를 만들어 냅니다.

- 포크조인 프레임워크는 ExecutorService의 구현 객체인 ForkJoinPool을 사용해서 작업 스레드를 관리합니다.

병렬 스트림 사용
- 자바 병렬 스트림은 백그라운드에서 포크조인 프레임워크가 사용하므로 병렬 처리가 용이합니다.
- parallelStream() 메소드는 컬렉션(List, Set)으로부터 병렬 스트림을 바로 리턴합니다.
- parallel() 메소드는 기존 스트림을 병렬 처리 스트림으로 변환 합니다.

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Stream;
public class ParallelExam {
public static void main(String[] args) {
Random random = new Random();
List<Integer> scores = new ArrayList<>();
for(int i = 0; i<100000000; i++) {
scores.add(random.nextInt(101));
}
double avg = 0.0;
long startTime = 0;
long endTime = 0;
long time = 0;
Stream<Integer> stream = scores.stream();
startTime = System.nanoTime();
avg = stream
.mapToInt(i-> i.intValue())
.average()
.getAsDouble();
endTime = System.nanoTime();
time = endTime - startTime;
System.out.println("avg: " + avg + ", 일반 스트림 처리 시간: " + time + "ns");
Stream<Integer> parallelStream = scores.parallelStream();
startTime = System.nanoTime();
avg = parallelStream
.mapToInt(i->i.intValue())
.average()
.getAsDouble();
endTime = System.nanoTime();
time = endTime - startTime;
System.out.println("avg: " + avg + ", 병렬 스트림 처리 시간: " + time + "ns");
}
}
결과 :
avg: 50.00118058, 일반 스트림 처리 시간: 155528300ns
avg: 50.00118058, 병렬 스트림 처리 시간: 69278400ns
병렬 처리 성능에 영향을 미치는 요인
- 요소의 수와 요소당 처리시간
- 스트림 소스의 종류
- 코어(Core)의 수
728x90
'JAVA > Java 기초' 카테고리의 다른 글
| 네트워크 기초(IP, TCP, UDP).java (0) | 2023.01.31 |
|---|---|
| 기본 타입 스트림.java (0) | 2023.01.31 |
| 입출력 스트림-2.java (0) | 2023.01.30 |
| 입출력 스트림.java (0) | 2023.01.30 |
| Optional 클래스.java (0) | 2023.01.30 |