Stream
## 예제는 filter라는 중간 연산만 있어서 실제 실행되지 않는다.
Stream.of("d2", "a2", "b1", "b3", "c")
.filter(s -> {
System.out.println("filter: " + s);
return true;
});
## forEach는 최종 연산이 있어 실제로 실행되어 결과가 나온다.
Stream.of("d2", "a2", "b1", "b3", "c")
.filter(s -> {
System.out.println("filter: " + s);
return true;
})
.forEach(s -> System.out.println("forEach: " + s));
## 결과 : 신기하게도 각 항복별로 filter-forEach의 pipeline으로 실행되는 것을 볼수 있다.
filter: d2
forEach: d2
filter: a2
forEach: a2
filter: b1
forEach: b1
filter: b3
forEach: b3
filter: c
forEach: c
## anyMatch에서 Start가 'A'인 것이 있으면 종료되는 Stream을 구성한것으로 아래 경우 2번만 실행되는것으로 map의 동작도 2번만 실행하게된다.
## 따라서 스트림 모든 원소를 대상으로 map이 최대한 적게 실행된다.
Stream.of("d2", "a2", "b1", "b3", "c")
.map(s -> {
System.out.println("map: " + s);
return s.toUpperCase();
})
.anyMatch(s -> {
System.out.println("anyMatch: " + s);
return s.startsWith("A");
});
// map: d2
// anyMatch: D2
// map: a2
// anyMatch: A2
## map - filter 순서로 비효율적임
Stream.of("d2", "a2", "b1", "b3", "c")
.map(s -> {
System.out.println("map: " + s);
return s.toUpperCase();
})
.filter(s -> {
System.out.println("filter: " + s);
return s.startsWith("A");
})
.forEach(s -> System.out.println("forEach: " + s));
// map: d2
// filter: D2
// map: a2
// filter: A2
// forEach: A2
// map: b1
// filter: B1
// map: b3
// filter: B3
// map: c
// filter: C
## filter - map 순서로 효율적으로 변경
Stream.of("d2", "a2", "b1", "b3", "c")
.filter(s -> {
System.out.println("filter: " + s);
return s.startsWith("a");
})
.map(s -> {
System.out.println("map: " + s);
return s.toUpperCase();
})
.forEach(s -> System.out.println("forEach: " + s));
// filter: d2
// filter: a2
// map: a2
// forEach: A2
// filter: b1
// filter: b3
// filter: c
IntStream.range(1, 4)
.forEach(System.out::println);
int sum = 0;
int count = 0;
for(Employee emp : emps) {
if (emp.getSalary() > 100000000) {
sum += emp.getSalary();
count++;
}
}
double average = (double) sum / count;
double average = emps.stream() # return type : Stream<Employee>
.filter(empp -> emp.getSalary() > 100000000)
.mapToInt(Employee::getSalary) # return type :IntStream
.average() # return type :OptionalDouble
.orElse(0); # return type :double
double avg = list.stream()
.mapToInt(Integer::intValue)
.average()
.orElse(0.0); // 값이 저장되지 않을 경우 defulat 0.0
list.stream()
.mapToInt(Integer::intValue)
.average()
.ifPresent(a -> System.out.println(a)); // 값이 존재하면 출력
int sum = sutentList.stream()
.map(Student :: getScore)
.reduce((a,b) -> a+b)
.get();
List<Student> sList = Arrays.asList(
new Student("Faker", 50, "a"),
new Student("Teddy", 30, "b"),
new Student("Effort", 10, "c"));
Map<String, Student> map = new HashMap<String,Student>();
map = sList.stream()
.collect(Collectors.toMap(Student::getName, Function.identity(),
(o1, o2) -> o1, HashMap::new));
동시성 (concurrent) : 멀티 스레드가 번갈아가며 실행하는 성질
- 싱글 코어 CPU를 이용한 멀티 작업은 병렬적으로 실행되는 것처럼 보이지만, 번갈아가며 실행하는 동시성 작업
병렬성 (parallel) : 멀티 코어를 이용해 동시에 실행하는 성질
- 데이터 병렬성 : 전체 데이터를 쪼개어 서브 데이터들로 만들고 이 데이터들을 병렬 처리해 작업을 빨리 끝내는 것(parallelStream)
- 작업 병렬성 : 서로 다른 작업을 병렬 처리하는 것(Web Server : 각각 브라우저에서 요청한 내용을 개별 스레드에서 병렬로 처리)
사용 예
public class PracticeExample{
public static void main(String[] args){
List<String> list = Arrays.asList("Faker", "Teddy", "Effort", "Wolf", "Bang", "Clid");
Stream<String> stream = list.parallelStream(); // parallesStream : 병렬처리
stream.forEach(PracticeExample :: print);
}
public static void print(String str) {
System.out.println(str + Thread.currentThread().getName());
}
}
-- 결과 --
Wolfmain
FakerForkJoinPool.commonPool-worker-3
TeddyForkJoinPool.commonPool-worker-1
ClidForkJoinPool.commonPool-worker-2
BangForkJoinPool.commonPool-worker-3
Effortmain