Epilogue๐โโ๏ธ
๋๋ ๋ํ๊ต๋๋ Java8์ดํ์ ์ถ๊ฐ๋ ์ฌํญ์ ๋ฐฐ์ฐ์ง ๋ชปํ๊ณ ,
์ค๋ฌด๋ ํญ.์. legacyํ๊ฒฝ์ ์ฝ๋๋ฅผ ๋ง์ด ์ ํ์ฌ์ ์ฌ์ค Lambda๋ Stream์ ๋ํ ํ์ฉ์ฝ๋๋ฅผ ๋ณธ ์ ๋ ๋ณ๋ก์๊ณ , ์ฌ์ค ๊ทธ๋ฅ List for loop๋๋ ค๋ ๋ฌธ์ ๊ฐ ์์์ผ๋๊น, ๋์ค์ ๊ณต๋ถํด์ผ์ง ํ๊ณ ๋ฏธ๋ฃจ๋ ๊ณต๋ถ๋ฅผ ๋ฆ์์ง๋ง ์ด์ ๋ผ๋ ์์ํด๋ณธ๋ค,,,
List<Student> list = Arrays.asList(
new Student("์ฐจ๋ฏผํ",100), new Student("์์ฌ", 99)
);
// java8 ์ด์ iterator๋ฅผ ํตํ for loop
for(Student student : list){
System.out.println(student.getName() + "score : " + student.getScore());
}
// java8 ์ดํ Stream์ ์ด์ฉํ for loop
Stream<Student> stream = list.stream();
stream.forEach(s -> {
System.out.println(s.getName() + " ์ ์ : "+s.getScore());
});
List<String> list = Arrays.asList(
"ํ๊ธธ๋", "์ค๋์ค", "๋๋ค์", "๋ฐ๋ณ๋ ฌ", "๊น์๋ฐ"
);
// ์์ฐจ์ฒ๋ฆฌ
Stream<String> stream = list.stream();
stream.forEach(ParallelExample :: print);
System.out.println();
// print >> ํ๊ธธ๋, ์ค๋์ค, ๋๋ค์, ๋ฐ๋ณ๋ ฌ, ๊น์๋ฐ
// ๋ณ๋ ฌ์ฒ๋ฆฌ
Stream<String> parallelStream = list.parallelStream();
parallelStream.forEach(ParallelExample :: print);
// print >> ๋๋ค์, ๊น์๋ฐ, ๋ฐ๋ณ๋ ฌ, ์ค๋์ค, ํ๊ธธ๋
์ค๊ฐ์ฒ๋ฆฌ :: ๋งคํ, ํํฐ๋ง, ์ ๋ ฌ์ ์ํ
์ต์ข ์ฒ๋ฆฌ :: ๋ฐ๋ณต, ์นด์ดํ , ํ๊ท , ์ดํฉ ๋ฑ์ ์ง๊ณ์ฒ๋ฆฌ๋ฅผ ์ํ
List<Student> studentList = Arrays.asList(
new Student("ํ๊ธธ๋", 60),
new Student("์ด์์ ", 95),
new Student("์ธ์ข
๋์", 100)
);
double avg = studentList.stream()
// ์ค๊ฐ์ฒ๋ฆฌ > ํ์๊ฐ์ฒด๋ฅผ ์ ์๋ก ๋งคํ
.mapToInt(Student :: getScore)
// ์ต์ข
์ฒ๋ฆฌ > ํ๊ท ์ ์
.average()
.getAsDouble();
// 1. ์ปฌ๋ ์
์ผ๋ก๋ถํฐ ์คํธ๋ฆผ ์ป๊ธฐ
List<Student> studentList = Arrays.asList(
new Student("ํ๊ธธ๋", 60),
new Student("์ด์์ ", 95),
new Student("์ธ์ข
๋์", 100)
);
Stream<Student> stream = studentList.stream();
stream.forEach(s -> System.out.println(s.getName()));
// 2. ๋ฐฐ์ด๋ก๋ถํฐ ์คํธ๋ฆผ ์ป๊ธฐ
// 2.1 String ๋ฐฐ์ด
String[] strArray = {"ํ๊ธธ๋" ,"์ด์์ ", "๊ฐ๊ฐ์ฐฌ"};
Stream<String> stStream = Arrays.stream(strArray);
stStream.forEach(s -> System.out.println(s));
// 2-2. int ๋ฐฐ์ด
int[] intArray = {1,23,54,5678,10};
IntStream intStream = Arrays.stream(intArray);
intStream.forEach(s -> System.out.println(s));
// 3. ์ซ์ ๋ฒ์๋ก๋ถํฐ ์คํธ๋ฆผ ์ป๊ธฐ
IntStream intRangeStream = IntStream.rangeClosed(1, 100); // cf) range(1,100) 1~99๊น์ง
intRangeStream.forEach(a -> sum +=a);
System.out.println("sum : "+sum);
// 4. ํ์ผ๋ก๋ถํฐ ์คํธ๋ฆผ ์ป๊ธฐ
Path path = Paths.get("src/main/java/study/stream/type/lineExample.txt");
Stream<String> fileStream ;
// 4-1. Files.lines() ๋ฉ์๋ ์ด์ฉ
fileStream = Files.lines(path, Charset.defaultCharset());
fileStream.forEach(System.out :: println);
System.out.println();
// 4-2.BufferedReader.lines() ๋ฉ์๋ ์ด์ฉ
File file = path.toFile();
FileReader fileReader = new FileReader(file);
BufferedReader br = new BufferedReader(fileReader);
fileStream = br.lines();
fileStream.forEach(System.out :: println);
// 5. ๋๋ ํ ๋ฆฌ๋ก๋ถํฐ ์คํธ๋ฆผ ์ป๊ธฐ
Path dirPath= Paths.get("D:\\IDE\\workspace");
Stream<Path> dirStream = Files.list(dirPath);
dirStream.forEach(p -> System.out.println(p.getFileName())) ;
๋๋์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ณตํด์ ์ถ์ํ๋ ๊ฒ์ ์ผ๋ฐ์ ์ผ๋ก ๋ฆฌ๋์ (Reduction)์ด๋ผ๊ณ ํ๋๋ฐ,
๋ฐ์ดํฐ์ ํฉ๊ณ, ํ๊ท ๊ฐ, ์ต๋๊ฐ, ์ต์๊ฐ ๋ฑ์ด ๋ํ์ ์ธ ๋ฆฌ๋์ ์ ๊ฒฐ๊ณผ๋ฌผ์ด๋ค.
๊ทธ๋ฌ๋ ์ปฌ๋ ์ ์ ์์๋ฅผ ๋ฆฌ๋์ ์ ๊ฒฐ๊ณผ๋ฌผ๋ก ๋ฐ๋ก ์ง๊ณ ํ ์ ์๋ ๊ฒฝ์ฐ
-> ์ง๊ณํ๊ธฐ ์ข๋๋ก ํํฐ๋ง, ๋งคํ, ์ ๋ ฌ, ๊ทธ๋ฃนํ ๋ฑ์ ์ค๊ฐ์ฒ๋ฆฌ๊ฐ ํ์ํ๋ค.
// ๋ก์ปฌ๋ณ์ ์๋ตํ ๋๋ค์ ํํ
double avgAge = list.stream() // ์ค๋ฆฌ์ง๋ ์คํธ๋ฆผ
.filter(s -> s.getSex() == Member.MALE) // ์ค๊ฐ์ฒ๋ฆฌ1 : ๋จ์ํ์๋ง ํํฐ๋ง
.mapToInt(Member::getAge) // ์ค๊ฐ์ฒ๋ฆฌ2 : ๋จ์ํ์ ๋์ด ํํฐ๋ง
.average() // ์ต์ข
์ฒ๋ฆฌ : ํฉ๊ณ๊ตฌํ๊ธฐ
.getAsDouble();
์ค๊ฐ์ฒ๋ฆฌ : ๋ฆฌํดํ์ ์ด ์คํธ๋ฆผ
์ต์ข ์ฒ๋ฆฌ : ๋ฆฌํดํ์ ๋ฆฌ ๊ธฐ๋ณธํ์ ์ด๊ฑฐ๋ OptinalXXX
์ข ๋ฅ | ์ฒ๋ฆฌ | ๋ฆฌํดํ์ | method |
---|---|---|---|
์ค๊ฐ์ฒ๋ฆฌ | ํํฐ๋ง | Stream IntStream LongStream DoubleStream | distinct() filter() |
๋งคํ | Stream IntStream LongStream DoubleStream | flatMap() flatMapToInt()... map() mapToInt()... asDoubleStream()... boxed() | |
์ ๋ ฌ | Stream IntStream LongStream DoubleStream | sorted() | |
๋ฃจํ | Stream IntStream LongStream DoubleStream | peek() | |
์ต์ข ์ฒ๋ฆฌ | ๋งค์นญ | Boolean | allMatch() anyMatch() noneMatch() |
์ง๊ณ | long OptinalXXX | count() findFirst() / max() / min() / average() / reduce()/ sum() | |
๋ฃจํ | void | forEach() | |
์์ง | R | collect() |
ํํฐ๋ง์ ์ค๊ฐ ์ฒ๋ฆฌ ๊ธฐ๋ฅ์ผ๋ก ์์๋ฅผ ๊ฑธ๋๋ ์ญํ
- distinct() : ์ค๋ณต์ ๊ฑฐ
- filter() : ๋งค๊ฐ๊ฐ์ผ๋ก ์ฃผ์ด์ง Predicate๊ฐ true๋ฅผ ๋ฆฌํดํ๋ ์์๋ง ํํฐ๋ง
// ์ค๋ณต์ ๊ฑฐ
Stream<String> stream = list.stream().distinct();
stream.forEach(System.out :: print);
System.out.println();
// ์ฑ์ด '์ '์จ๋ฉด์ ์ค๋ณต์ ๊ฑฐ
Stream<String> sinStream = list.stream()
.distinct()
.filter(s-> s.startsWith("์ "));
sinStream.forEach(System.out :: print);
๋งคํ์ ์ค๊ฐ ์ฒ๋ฆฌ ๊ธฐ๋ฅ์ผ๋ก ์คํธ๋ฆผ์ ์์๋ฅผ ๋ค๋ฅธ์์๋ก ๋์ฒดํ๋ ์์ ์ด๋ค.
List<String> inputList = Arrays.asList("java8 lambda", "stream mapping");
// ๋ณต์๊ฐ์ ์์๋ก ๋์ฒด
inputList.stream()
.flatMap(data -> Arrays.stream(data.split(" ")))
.forEach(System.out :: println);
// result >
java8
lambda
stream
mapping
// String ๋ฐฐ์ด์ , ๋จ์๋ก ์ง๋ฅธ ํ int[]๋ฐฐ์ด๋ก ๋ณํ
List<String> inputList2 = Arrays.asList("1,2,3","4,5,67","8,9,20");
inputList2.stream()
.flatMapToInt(data-> {
String[] strArr = data.split(",");
int[] intArr = new int[strArr.length];
for(int i=0;i<intArr.length;i++){
intArr[i] = Integer.parseInt(strArr[i].trim());
}
return Arrays.stream(intArr);
})
.forEach(System.out::println);
// result >
1
2
3
4
5
67
8
9
20
List<Student> studentList = Arrays.asList(
new Student("ํ๊ธธ๋", 10),
new Student("๊น๋๋", 20),
new Student("์ฐจ์๋", 30)
);
studentList.stream()
.mapToInt(s-> s.getScore())
.forEach(System.out :: println);
โ LongStream์ ong ์์๋ฅผ double์์๋ก ํ์ ๋ณํํด์ DoubleStream์ ์์ฑ
int[] intArray = {1,2,3,4,5};
// int -> double ๋ก ๋ณํ
IntStream stream = Arrays.stream(intArray);
stream.asDoubleStream().forEach(System.out :: println);
// boxed (int -> Integer)
stream = Arrays.stream(intArray);
stream
.boxed()
.forEach(System.out :: println);
โ
์คํธ๋ฆผ์ ์์๊ฐ ์ต์ข ์ฒ๋ฆฌ๋๊ธฐ ์ ์ ์ค๊ฐ ๋จ๊ณ์์ ์์๋ฅผ ์ ๋ ฌํด์ ์ต์ข ์ฒ๋ฆฌ ์์๋ฅผ ๋ณ๊ฒฝ
โป๊ฐ์ฒด ์์์ผ ๊ฒฝ์ฐ์๋ ํด๋์ค๊ฐ Comparable์ ๊ตฌํํ์ง ์์ผ๋ฉด sorted()๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ClassCastException์ด ๋ฐ์ํ๋ค. ๋ฐ๋ผ์ Comparable์ด ๊ตฌํ๋ ์์์์ ์ฌ์ฉ๊ฐ๋ฅํ๋ค.
public class Student implements Comparable<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;
}
@Override
public int compareTo(Student o) {
return Integer.compare(score, o.getScore());
}
}
// ์ซ์ ์์์ธ ๊ฒฝ์ฐ
IntStream intStream = Arrays.stream(new int[]{5,3,2,1,4});
intStream.sorted()
.forEach(System.out :: println);
// ๊ฐ์ฒด ์์์ผ ๊ฒฝ์ฐ
List<Student> list = Arrays.asList(
new Student("๊น๋๋", 90),
new Student("์์ฌ", 99),
new Student("์๋", 20)
);
list.stream()
.sorted()
.forEach(s-> System.out.println(s.getScore()));
// ์ญ์
list.stream()
.sorted(Comparator.reverseOrder())
.forEach(s-> System.out.println(s.getScore()));
์์ ์ ์ฒด๋ฅผ ๋ฐ๋ณตํ๋๊ฒ.
- peek() : ์ค๊ฐ์ฒ๋ฆฌ ๋จ๊ณ์ ๋ฉ์๋์ด๋ฏ๋ก ,๋ฐ๋์ ์ต์ข ์ฒ๋ฆฌ ๋จ๊ณ์ ๋ฉ์๋ ํธ์ถ
- forEach() : ์ต์ข ์ฒ๋ฆฌ ๋จ๊ณ์ ๋ฉ์๋, ํด๋น ๋ฉ์๋ ํธ์ถ์ดํ sum()๊ฐ์ ์ต์ข ์ฒ๋ฆฌ ๋ฉ์๋ ํธ์ถํ๋ฉด ์๋๋ค
int[] intArr = {1,2,3,4,5};
// peek()๋ฅผ ๋ง์ง๋ง์ ํธ์ถํ ๊ฒฝ์ฐ
Arrays.stream(intArr)
.filter(a -> a% 2 == 0)
.peek(a-> System.out.println(a)); // ๋์ํ์ง ์์
// ์ต์ข
์ฒ๋ฆฌ ๋ฉ์๋๋ฅผ ๋ง์ง๋ง์ ํธ์ถํ ๊ฒฝ์ฐ
int total = Arrays.stream(intArr)
.filter(a -> a% 2 == 0)
.peek(a-> System.out.println(a)) // ๋์ํจ
.sum();
System.out.println("total : "+total);
// forEach()๋ฅผ ๋ง์ง๋ง์ ํธ์ถํ ๊ฒฝ์ฐ
Arrays.stream(intArr)
.filter(a -> a% 2 == 0)
.forEach(System.out :: println);
์คํธ๋ฆผํด๋์ค๋ ์ต์ข ์ฒ๋ฆฌ ๋จ๊ณ์์ ์์๋ค์ด ํน์ ์กฐ๊ฑด์ ๋ง์กฑํ๋์ง ์กฐ์ฌํ ์ ์๋๋ก ์ ๊ณต
- allMatch() : ๋ชจ๋ ์์๋ค์ด ๋งค๊ฐ๊ฐ์ผ๋ก ์ฃผ์ด์ง Predicate์ ์กฐ๊ฑด์ ๋ง์กฑํ๋์ง
- anyMatch() : ์ต์ํ ํ ๊ฐ์ ์์๊ฐ ๋งค๊ฐ๊ฐ์ผ๋ก ์ฃผ์ด์ง Predicate์ ์กฐ๊ฑด์ ๋ง์กฑํ๋์ง
- noneMatch() : ๋ชจ๋ ์์๋ค์ด ๋งค๊ฐ๊ฐ์ผ๋ก ์ฃผ์ด์ง Predicate์ ์กฐ๊ฑด์ ๋ง์กฑํ์ง ์๋์ง
int[] intArr = {2,4,5};
boolean result = Arrays.stream(intArr)
.allMatch(a -> a%2 ==0);
// print > false
boolean result1 = Arrays.stream(intArr)
.anyMatch(a -> a%3 ==0);
// print > false
boolean result2 = Arrays.stream(intArr)
.noneMatch(a -> a%3 ==0);
// print > false
์ต์ข ์ฒ๋ฆฌ ๊ธฐ๋ฅ์ผ๋ก ์์๋ค์ ์ฒ๋ฆฌํด์ ์นด์ดํ , ํฉ๊ณ, ํ๊ท ๊ฐ, ์ต๋๊ฐ, ์ต์๊ฐ๋ฑ๊ณผ ๊ฐ์ด ํ๋์ ๊ฐ์ผ๋ก ์ฐ์ถ
์ง๊ณ๋ ๋๋์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ณตํด์ ์ถ์ํ๋ ๋ฆฌ๋์ (reduction)์ด๋ผ๊ณ ๋ณผ ์ ์๋ค.
// ๊ฐ์
long count = Arrays.stream(new int[]{1,2,3,4,5})
.filter(n-> n%2 ==0)
.count();
// print > 2
// ํฉ๊ณ
long sum = Arrays.stream(new int[]{1,2,3,4,5})
.filter(n-> n%2 ==0)
.sum();
// print > 6
// ํ๊ท ๊ฐ
double avg = Arrays.stream(new int[]{1,2,3,4,5})
.filter(n-> n%2 ==0)
.average()
.getAsDouble();
// print > 3.0
// ์ต๋๊ฐ
int max = Arrays.stream(new int[]{1,2,3,4,5})
.filter(n-> n%2 ==0)
.max()
.getAsInt();
// print > 4
// ์ต์๊ฐ
int min = Arrays.stream(new int[]{1,2,3,4,5})
.filter(n-> n%2 ==0)
.min()
.getAsInt();
// print > 2
๋จ์ํ ์ง๊ณ ๊ฐ๋ง ์ ์ฅํ๋ ๊ฒ์ด ์๋๋ผ, ์ง๊ณ ๊ฐ์ด ์กด์ฌํ์ง ์์ ๊ฒฝ์ฐ ๋ํดํธ ๊ฐ์ ์ค์ ํ ์ ์๊ณ ,
์ง๊ณ ๊ฐ์ ์ฒ๋ฆฌํ๋ Consumer๋ ๋ฑ๋กํ ์ ์๋ค.
List<Integer> list = new ArrayList<>();
// ์ปฌ๋ ์
์ ์์๊ฐ ์ถ๊ฐ๋์ง ์์ ์ํ -> NoSuchElementException ์์ธ๋ฐ์
double avg = list.stream()
.mapToInt(Integer :: intValue)
.average()
.getAsDouble();
System.out.println(avg);
// ๋ฐฉ๋ฒ1) Optinal.isPresent() ๋ฉ์๋๋ก ํ๊ท ๊ฐ ์ฌ๋ถ๋ฅผ ํ์ธ.
OptionalDouble optional = list.stream()
.mapToInt(Integer::intValue)
.average();
if(optional.isPresent()){
System.out.println("(method1)avg : " + optional.getAsDouble());
}else {
System.out.println("(method1)avg : 0.0");
}
// ๋ฐฉ๋ฒ2) orElse() ๋ฉ์๋๋ฅผ ์ด์ฉํ์ฌ default๊ฐ์ ์ค์ .
double avg = list.stream()
.mapToInt(Integer::intValue)
.average()
.orElse(0.0);
System.out.println("(method2)avg : " + avg);
// ๋ฐฉ๋ฒ3) ํ๊ท ๊ฐ์ด ์์ ๊ฒฝ์ฐ์๋ง
list.stream()
.mapToInt(Integer::intValue)
.average()
.ifPresent(a-> System.out.println("(method3) avg : "+a));
๋ค์ํ ์ง๊ณ ๊ฒฐ๊ณผ๋ฌผ์ ๋ง๋ค ์ ์๋๋ก reduce()๋ฉ์๋ ์ ๊ณต
List<Student> studentList = Arrays.asList(
new Student("๊น๋๋", 82),
new Student("๋๋ค๋", 90),
new Student("์ ํจ๋ฒ", 57)
);
// ํ์๋ค์ ์ด์ ๊ตฌํ๊ธฐ
// ๋ฐฉ๋ฒ1) sum()์ด์ฉ
int sum1 = studentList.stream()
.mapToInt(Student::getScore)
.sum();
// ๋ฐฉ๋ฒ2) reduce(Operator) ์ด์ฉ, ์คํธ๋ฆผ ์์ ์๋ ๊ฒฝ์ฐ NoSuchElementException ๋ฐ์
int sum2 = studentList.stream()
.map(Student::getScore)
.reduce((a,b) -> a+b)
.get();
// ๋ฐฉ๋ฒ3) reduce(identity, Operator) ์ด์ฉ, ์คํธ๋ฆผ ์์ ์๋ ๊ฒฝ์ฐ, 0.0
int sum3 = studentList.stream()
.map(Student::getScore)
.reduce(0, (a,b) -> a+b);
์คํธ๋ฆผ์ ์์๋ค์ ํํฐ๋ง ๋๋ ๋งคํํ ํ ์์๋ค์ ์์งํ๋ ์ต์ข ์ฒ๋ฆฌ ๋ฉ์๋์ธ collect()๋ฅผ ์ ๊ณต
์ด ๋ฉ์๋๋ฅผ ์ด์ฉํ๋ฉด ํ์ํ ์์๋ง ์ปฌ๋ ์ ์ผ๋ก ๋ด์ ์ ์๊ณ , ์์๋ค์ ๊ทธ๋ฃนํํ ํ ์ง๊ณํ ์ ์๋ค.
List<Student> list = Arrays.asList(
new Student("๊น๋๋", 10, Student.Sex.FEMALE),
new Student("๊ฐ์ฐฌํฌ", 35, Student.Sex.MALE),
new Student("ํฉ์ง์ด", 98, Student.Sex.FEMALE),
new Student("๋ฐ์ง์ฑ", 50, Student.Sex.MALE)
);
// ์ ์ฒด ํ์ ์ค ๋จํ์๋ง ํํฐ๋งํด์ ๋ณ๋์ List ์์ฑํ๊ธฐ
Stream<Student> stream = list.stream();
Stream<Student> maleStream = stream.filter(s->s.getSex()== Student.Sex.MALE);
// List์ Student๋ฅผ ์์งํ๋ Collector๋ฅผ ์ป๊ธฐ
Collector<Student, ? , List<Student>> collector = Collectors.toList();
// Stream์ collect()๋ฉ์๋๋ก Student๋ฅผ ์์งํด์ ์๋ก์ด List๋ฅผ ์ป๋๋ค.
List<Student> maleList = maleStream.collect(collector);
// ๋ณ์ ์๋ต ๋ฒ์
List<Student> maleScoreList = list.stream()
.filter(s-> s.getSex() == Student.Sex.MALE)
.collect(Collectors.toList());
maleScoreList.stream().forEach(s-> System.out.println(s.getScore()));
collect(Supplier, BiConsumer<R, ? super T>, BiConsumer<R,R>)
Supplier : ์์๋ค์ด ์์ง๋ ์ปจํ ์ด๋(R)์ ์์ฑ
BiConsumer<R, ? super T> : ์ปจํ ์ด๋ ๊ฐ์ฒด(R)์ ์์(T)๋ฅผ ์์งํ๋ ์ญํ
BiConsumer<R,R> : ์ปจํ ์ด๋ ๊ฐ์ฒด(R)๋ฅผ ๊ฒฐํฉํ๋ ์ญํ .
private List<Student> list; // ์์๋ฅผ ์ ์ฅํ ์ปฌ๋ ์
public MaleStudent(){ // ์์ฑ์
list = new ArrayList<>();
System.out.println("["+ Thread.currentThread().getName()+"] MaleStudent");
}
public void accumulate(Student student){ //์์๋ฅผ ์์งํ๋ ๋ฉ์๋
list.add(student);
System.out.println("["+ Thread.currentThread().getName()+"] accumulate()");
}
public void combine(MaleStudent other){ // ๋ MaleStudent๋ฅผ ๊ฒฐํฉํ๋ ๋ฉ์๋ (๋ณ๋ ฌ์ฒ๋ฆฌ์๋ง ํธ์ถ)
list.addAll(other.getList());
System.out.println("["+ Thread.currentThread().getName()+"] combine()");
}
public List<Student> getList(){ // ์์๊ฐ ์ ์ฅ๋ ์ปฌ๋ ์
์ ๋ฆฌํดํด
return list;
}
// 1.์ ์ฒด ํ์ List์์ Stream ์ป๊ธฐ
Stream<Student> stream = list.stream();
// 2.๋จํ์๋ง ํํฐ๋งํด์ Stream ์ป๊ธฐ
Stream<Student> maleStream = stream.filter(s->s.getSex()== Student.Sex.MALE);
// 3.MaleStudent๋ฅผ ๊ณต๊ธํ๋ Supplier๋ฅผ ์ป๋๋ค.
Supplier<MaleStudent> supplier = () -> new MaleStudent();
// 4.MaleStudent์ Student๋ฅผ ๋งค๊ฐ๊ฐ์ผ๋ก ๋ฐ์์ MaleStudent์ accumulate()๋ฉ์๋๋ก Student๋ฅผ ์์งํ๋ BiConsumer๋ฅผ ์ป๋๋ค
BiConsumer<MaleStudent, Student> accmulator = (ms, s) -> ms.accumulate(s);
// 5. ๋ ๊ฐ์ MaleStudent๋ฅผ ๋งค๊ฐ๊ฐ์ผ๋ก ๋ฐ์ combine()๋ฉ์๋๋ก ๊ฒฐํฉํ๋ BiConsumer๋ฅผ ์ป๋๋ค.
BiConsumer<MaleStudent, MaleStudent> combiner = (ms1, ms2) -> ms1.combine(ms2);
// 6. supplier๊ฐ ์ ๊ณตํ๋ MaleStudent์ accumulator๊ฐ Student๋ฅผ ์์งํด์ ์ต์ข
์ฒ๋ฆฌ๋ MaleStudent๋ฅผ ์ป๋๋ค.
MaleStudent maleStudent = maleStream.collect(supplier, accmulator, combiner);
// ๋ฉ์๋ ์ฐธ์กฐ ๋ฒ์
MaleStudent maleStudent2 = list.stream()
.filter(s->s.getSex()== Student.Sex.MALE)
.collect(MaleStudent::new, MaleStudent::accumulate, MaleStudent::combine);
maleStudent2.getList().stream()
.forEach(s-> System.out.println(s.getName()));
// result >
[main]
[main] accumulate()
[main] accumulate()
๊ฐ์ฐฌํฌ
๋ฐ์ง์ฑ
Collector<T, ?, Map<K, List>
- T๋ฅผ K๋ก ๋งคํํ๊ณ , K ํค์ ์ ์ฅ๋ List์ T๋ฅผ ์ ์ฅํ Map ์์ฑ
- groupBy(Function<T,K> classifier)
List<Student> list = Arrays.asList(
new Student("๊น๋๋", 10, Student.Sex.FEMALE, Student.City.Seoul),
new Student("๊ฐ์ฐฌํฌ", 35, Student.Sex.MALE, Student.City.Seoul),
new Student("ํฉ์ง์ด", 98, Student.Sex.FEMALE, Student.City.Busan),
new Student("๋ฐ์ง์ฑ", 50, Student.Sex.MALE, Student.City.Seoul)
);
/**
* ํ์๋ค์ ์ฑ๋ณ๋ก ๊ทธ๋ฃนํํ๊ณ , ๊ฐ์ ๊ทธ๋ฃน์ ์ํ๋ ํ์ List๋ฅผ ์์ฑํ ๋ค,
* ์ฑ๋ณ์ ํค๋ก, ํ์List๋ฅผ ๊ฐ์ผ๋ก ๊ฐ๋ Map์ ์์ฑํ๋ค.
*/
// 1. ์ ์ฒดํ์ List์์ Stream ์ป๊ธฐ
Stream<Student> stream = list.stream();
// 2. Student๋ฅผ Student.Sex๋ก ๋งคํํ๋ Function์ ์ป๋๋ค
Function<Student, Student.Sex> classifier = Student::getSex;
// 3. Student.Sex๊ฐ ํค๊ฐ ๋๊ณ , ๊ทธ๋ฃนํ ๋ List<Student>๊ฐ ๊ฐ์ธ Map์ ์์ฑํ๋ Collector๋ฅผ ์ป๋๋ค
Collector<Student, ? , Map<Student.Sex, List<Student>>> collector = Collectors.groupingBy(classifier);
// 4. Stream์ collect() ๋ฉ์๋๋ก Student๋ฅผ Student.Sex๋ณ๋ก ๊ทธ๋ฃนํฝํด์ Map์ ์ป๋๋ค.
Map<Student.Sex, List<Student>> mapBySex = stream.collect(collector);
// ๋ณ์ ์ ๊ฑฐ ๋ฒ์
Map<Student.Sex, List<Student>> mapBySex1 = list.stream()
.collect(Collectors.groupingBy(Student :: getSex));
mapBySex1.get(Student.Sex.MALE).stream()
.forEach(s-> System.out.println(s.getName()));
// result > ๊ฐ์ฐฌํฌ ๋ฐ์ง์ฑ
/**
* ํ์๋ค์ ๊ฑฐ์ฃผ ๋์๋ณ๋ก ๊ทธ๋ฃนํํ๊ณ , ๊ฐ์ ๊ทธ๋ฃน์ ์ํ๋ ํ์๋ค์ ์ด๋ฆ์ List๋ก ์์ฑํ ํ
* ๊ฑฐ์ฃผ ๋์๋ฅผ ํค๋ก, ์ด๋ฆ List๋ฅผ ๊ฐ์ผ๋ก ๊ฐ๋ Map์ ์์ฑ
*/
// 1. ์ ์ฒดํ์ List์์ Stream ์ป๊ธฐ
Stream<Student> cityStream = list.stream();
// 2. Student๋ฅผ Student.City๋ก ๋งคํํ๋ Function์ ์ป๋๋ค
Function<Student, Student.City> cityClassifier = Student :: getCity;
// 3. Student๋ฅผ Student.Name๋ก ๋งคํํ๋ Function์ ์ป๋๋ค
Function<Student, String> mapper = Student :: getName;
// 4. Student์ ์ด๋ฆ์ List์ ์์งํ๋ Collerctor๋ฅผ ์ป๋๋ค.
Collector<String, ? , List<String>> collector1 = Collectors.toList();
Collector<Student, ?, List<String>> collector2 = Collectors.mapping(mapper, collector1);
// 5. Student.City๊ฐ ํค๊ณ ๊ทธ๋ฃนํ๋ ์ด๋ฆ List๊ฐ ๊ฐ์ธ Map์ ์์ฑํ๋ Collector๋ฅผ ์ป๋๋ค.
Collector<Student, ? , Map<Student.City, List<String>>> collector3 = Collectors.groupingBy(cityClassifier, collector2);
// 6. Stream์ collect๋ฉ์๋๋ก Student๋ฅผ Student.City๋ณ๋ก ๊ทธ๋ฃนํํด์ Map์ ์ป๋๋ค.
Map<Student.City, List<String>> mapByCity = cityStream.collect(collector3);
// ๋ณ์ ์๋ต ๋ฒ์
Map<Student.City, List<String>> mapByCity2 = list.stream()
.collect(
Collectors.groupingBy(
Student::getCity, Collectors.mapping(Student::getName, Collectors.toList())
)
);
mapByCity2.get(Student.City.Busan).stream()
.forEach(s-> System.out.println(s));
// result > ํฉ์ง์ด
/**
* ํ์๋ค์ ์ฑ๋ณ๋ก ๊ทธ๋ฃนํํ ๋ค์ ๊ฐ์ ๊ทธ๋ฃน์ ์ํ๋ ํ์๋ค์ ํ๊ท ์ ์๋ฅผ ๊ตฌํ๊ณ ,
* ์ฑ๋ณ์ ํค๋ก, ํ๊ท ์ ์๋ฅผ ๊ฐ์ผ๋ก ๊ฐ๋ Map์ ์์ฑํ๋ค.
*/
Stream<Student> stream = list.stream();
Function<Student, Student.Sex> classifier = Student::getSex;
// Student๋ฅผ ์ ์๋ก ๋งคํํ๋ ToDoubleFunction์ ์ป๋๋ค
ToDoubleFunction<Student> mapper = Student::getScore;
// ํ์ ์ ์์ ํ๊ท ์ ์ฐ์ถํ๋ Collector๋ฅผ ์ป๋๋ค
Collector<Student, ? , Double> collector1 = Collectors.averagingDouble(mapper);
// Student.Sex๊ฐ ํค๊ณ , ํ๊ท ์ ์๊ฐ Double์ธ ๊ฐ์ธ Map์ ์์ฑํ๋ Collector๋ฅผ ์ป๋๋ค.
Collector<Student, ? , Map<Student.Sex, Double>> collector2 = Collectors.groupingBy(classifier, collector1);
// Stream์ collect() ๋ฉ์๋๋ก Student๋ฅผ Student.Sex๋ณ๋ก ๊ทธ๋ฃนํํ์ฌ Map์ ์ป๋๋ค.
Map<Student.Sex, Double> mapByScore = stream.collect(collector2);
// ๋ณ์ ์ ๊ฑฐ ๋ฒ์
Map<Student.Sex, Double> map = list.stream()
.collect(
Collectors.groupingBy(
Student::getSex,
Collectors.averagingDouble(Student::getScore)
)
);
System.out.println(map.get(Student.Sex.MALE));
๋์์ฑ :๋ฉํฐ์์ ์ ์ํด ๋ฉํฐ์ค๋ ๋๊ฐ ๋ฒ๊ฐ์๊ฐ๋ฉฐ ์คํํ๋ ์ฑ์ง
๋ณ๋ ฌ์ฑ : ๋ฉํฐ ์์ ์ ์ํด ๋ฉํฐ ์ฝ์ด๋ฅผ ์ด์ฉํด์ ๋์์ ์คํํ๋ ์ฑ์ง
// ๋ฉ์๋ ์ฐธ์กฐ ๋ฒ์
MaleStudent maleStudent2 = list.parallelStream()
.filter(s->s.getSex()== Student.Sex.MALE)
.collect(MaleStudent::new, MaleStudent::accumulate, MaleStudent::combine);
maleStudent2.getList().stream()
.forEach(s-> System.out.println(s.getName()));
// result >
[main] MaleStudent
[main] MaleStudent
[ForkJoinPool.commonPool-worker-3] MaleStudent
[ForkJoinPool.commonPool-worker-5] MaleStudent
[ForkJoinPool.commonPool-worker-3] accumulate()
[main] accumulate()
[ForkJoinPool.commonPool-worker-3] combine()
[main] combine()
[main] combine()
๊ฐ์ฐฌํฌ
๋ฐ์ง์ฑ
์ปฌ๋ ์ ์ ์์์ ์๊ฐ ์ ๊ณ ์์๋น ์ฒ๋ฆฌ ์๊ฐ์ด ์งง์ผ๋ฉด ์์ฐจ์ฒ๋ฆฌ๊ฐ ๋ณ๋ ฌ์ฒ๋ฆฌ๋ณด๋ค ๋น ๋ฅด๋ค
ArrayList, ๋ฐฐ์ด์ ์ธ๋ฑ์ค๋ก ์์๋ฅผ ๊ด๋ฆฌํ๊ธฐ ๋๋ฌธ์ ๋ณ๋ ฌ์ฒ๋ฆฌ์ ์๊ฐ์ด ์ ์ฝ๋๋ค.
๋ฐ๋ฉด์ HashSet, TreeSet, LinkedList๋ ์๋์ ์ผ๋ก ๋ณ๋ ฌ์ฒ๋ฆฌ๊ฐ ๋ฆ๋ค
์ฑ๊ธ์ฝ์ด์ผ์๋ก ์์ฐจ์ฒ๋ฆฌ๊ฐ ๋น ๋ฅด๋ค. ๊ณง, ์ฝ์ด์ ์๊ฐ ๋ง์์๋ก ๋ณ๋ ฌ์ฒ๋ฆฌ ์ฒ๋ฆฌ์๋๊ฐ ๋นจ๋ผ์ง๋ค.
โป [์ด๊ฒ์ด ์๋ฐ๋ค ์ ์ฉ๊ถJava ํ๋ก๊ทธ๋๋ฐ ์ ๋ณต2] ํด๋น ์ฑ ์ ์ฐธ๊ณ ํ๋ฉฐ ์ ๋ฆฌํ ๋ด์ฉ์ ๋๋ค.