์คํธ๋ฆผ : ์ปฌ๋ ์ ์ด๋ ๋ฐฐ์ด์ ๋ฐ๋ณต์ ๋ฉ์ง๊ฒ ์ฒ๋ฆฌํ๋ ๊ธฐ๋ฅ
- ๋ฉํฐ ์ค๋ ๋ ์ฝ๋๋ฅผ ๊ตฌํํ์ง ์์๋ ๋ฐ์ดํฐ๋ฅผ ํฌ๋ช ํ๊ฒ ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌํจ.
//๊ธฐ์กด ์ฝ๋
List<Dish> lowCaloricDishes = new ArrayList<>();
for(Dish d : menu){
if(d.getCalories() < 400){
lowCaloricDishes.add(d);
}
}
Collections.sort(lowCaloricDishes, new Comparator<Dish>(){
public int compare(Dish d1, Dish d2){
return Integer.compare(d1.getCalories(), d2.getCalories());
}
});
List<String> lowCaloricDishesName = new ArrayList<>();
for(Dish d: lowCaloricDishes){
lowCaloricDishesName.add(d.getName());
}
//java 8
List<String> lowCaloricDishesName = menu.stream()
.filter(d->d.getCalories() < 400)
.sorted(comparing(Dishes::getCalories))
.map(Dish::getName)
.collect(toList());- ์ ์ธํ์ผ๋ก ์ฝ๋ ๊ตฌํ
- ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๊ณผ์ ์ ๋ณ๋ ฌ๋ก ํจ -> ๋ฝ์ ๊ฑธ ํ์๊ฐ ์์ - ์ฑ๋ฅ์ด ์ข์์ง
- ์ ์ฐ์ฑ์ด ์ข์์ง
๋ฐ์ดํฐ ์ฒ๋ฆฌ ์ฐ์ฐ์ ์ง์ํ๋๋ก ์์ค์์ ์ถ์ถ๋ ์ฐ์๋ ์์
- ์ฐ์๋ ์์
- ์์ค : ์ปฌ๋ ์ , ๋ฐฐ์ด , I/O ์์ ๋ฑ์ ๋ฐ์ดํฐ ์ ๊ณต ์์ค๋ก ๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ์๋น
- ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์ฐ์ฐ : filter, map, reduce, find, match, sort ๋ฑ
- ํ์ดํ๋ผ์ด๋
- ๋ด๋ถ ๋ฐ๋ณต
= ๋ฐ์ดํฐ๋ฅผ ์ธ์ ๊ณ์ฐ ํ๋๋
์ปฌ๋ ์ - ์ปฌ๋ ์ ์ด ์ถ๊ฐ๋๊ธฐ ์ ์ ๊ณ์ฐ๋์ด์ผํจ - ์ปฌ๋ ์ ์ ๋ชจ๋ ์์๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํด์ผํจ, ์ถ๊ฐํ๋ ค๋ ์์๋ ๋ฏธ๋ฆฌ ๊ณ์ฐ ๋์ด์ผํจ.
์คํธ๋ฆผ
-
์์ฒญํ ๋๋ง ์์๋ฅผ ๊ณ์ฐ - ์ฌ์ฉ์๊ฐ ์์ฒญํ ๋๋ง ๊ฐ์ ๊ณ์ฐํจ
-
๋ฑ ํ๋ฒ๋ง ํ์ํจ - ํ์๋ ์คํธ๋ฆผ์ ์์๋ ์๋น๋จ.
List<String> title = Arrays.asList("Java8", "In", "Action"); Stream<String> s = title.stream(); s.forEach(System.out::println); s.forEach(System.out::println); //error
-
์ธ๋ถ๋ฐ๋ณต(์ปฌ๋ ์ ์์ ์ง์ ์์๋ฅผ ๋ฐ๋ณต)๊ณผ ๋ด๋ถ๋ฐ๋ณต(์คํธ๋ฆผ์์ ์์์ ์ฒ๋ฆฌ)
- ๋ด๋ถํจ์๊ฐ ์ข์ ์ด์
- ํฌ๋ณํ๊ฒ ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌํ๊ฑฐ๋ ๋ ์ต์ ํ๋ ๋ค์ํ ์์๋ก ์ฒ๋ฆฌํ ์ ์์.
- ์ฐ๋ฆฌ๊ฐ ์ ๊ฒฝ์ฐ์ง ์์๋๋จ
- ๋ด๋ถํจ์๊ฐ ์ข์ ์ด์
์ค๊ฐ์ฐ์ฐ
List<String> menus =
menu.stream()
.filter(d -> {
System.out.println("filtering" + d.getName());
return d.getCalories() > 300;
})
.map(d -> {
System.out.println("mapping"+ d.getName());
return d.getName();
})
.limit(3)
.collect(toList());filtering pork
mapping pork
filtering beef
mapping beef
filtering chicken
mapping chicken
//๊ทธ ์ด์์ ํํฐ๋ง ํ์ง ์์
- Filter, map, limit, sorted, distinct
์ต์ข ์ฐ์ฐ
- Count, forEach, collect
ํ๋ ๋์ผ์ดํธ๋ก ํํฐ๋ง
List<Dish> vegetarianMenu = menu.stream()
.filter(Dish::isVegetarian)
.collect(toList());๊ณ ์ ์์ ํํฐ๋ง
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream()
.filter(i -> i % 2 ==0)
.distinct() //์ค๋ณต ์์ ์ ๊ฑฐ
.forEach(System.out::println);์คํธ๋ฆผ ์ถ์
List<Dish> dishes = menu.stream()
.filter(d -> d.getCalories() > 300)
.limit(3) //์ต๋ n๊ฐ์ ์์๋ฅผ ๋ฐํ
.collect(toList());์์ ๊ฑด๋๋ฐ๊ธฐ
List<Dish> dishes = menu.stream()
.filter(d -> d.getCalories() > 300)
.skip(2) // n ๋จ๊ณ ๊ฑด๋ ๋ฐ๊ธฐ
.collect(toList())flatMap
List<String> uniqueCharacters =
words.stream()
.map(w -> w.split(""))
.flatMap(Arrays::stream) //ํ๋ฉดํ๋ ์คํธ๋ฆผ์ ๋ฐํ ๋ฐฐ์ด์ด ์๋ ์์ ํ๋์ฉ
.distinct()
.collect(Collectors.toList()); ํ๋ ๋์ผ์ดํธ๊ฐ ์ ์ด๋ ํ ์์์ ์ผ์นํ๋ ์ง ํ์ธ
if(menu.stream().anyMatch(Dish::isVegetarian)){
System.out.println("The menu is (someWhat) vegetarian friendly!");
}๋ชจ๋ ์์์ ์ผ์นํ๋์ง ๊ฒ์ฌ
boolean isHealthy = menu.stream().allMatch(d -> d.getCalories < 1000);๋ฐ๋
boolean isHealty = menu.stream().nonMatch(d -> d.getCalories() >= 1000);์์ ๊ฒ์
Optiopnal<Dish> dish = menu.stream()
.filter(Dish::isVegetarian)
.findAny();Optional ์ด๋
๊ฐ์ ์กด์ฌ๋ ๋ถ์ฌ ์ฌ๋ถ๋ฅผ ํํํ๋ ์ปจํ ์ด๋ ํด๋์ค
- isPresent() ๊ฐ ํฌํจ ์ฌ๋ถ
- ifPresent(Consumer block)
- T get() ๊ฐ ์กด์ฌํ๋ฉด ๋ดํ ์์ผ๋ฉด NoSuchElementException
- T orElse(T other)
findFirst() - ์ฒซ๋ฒ์งธ ์์
List<Integer> somNumbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> firstSquareDivisibleByThree = someNumbers.stream()
.map(x -> x*x)
.filter(x -> x%3 == 0)
.findFirst();์์์ ํฉ
๊ธฐ์กด
int sum = 0;
for (int x ; numbers){
sum+=x;
}-> stream
int sum = numbers.stream().reduce(0, (a, b) -> a + b);int sum = numbers.stream().reduce(0, Integer::sum);-> ์ด๊ธฐ๊ฐ์ด ์๋ค๋ฉด
Optional<Integer> max = numbers.stream().reduce(Integer::max);- Optional ๊ฐ์ฒด๋ฅผ ๋ฆฌํดํจ
reduce ๋ฉ์๋์ ์ฅ์ ๊ณผ ๋ณ๋ ฌํ
-
๋ณ๋ ฌ๋ก reduce๋ฅผ ์คํํ ์ ์์
int sum = numbers.parallelStream().reduce(0, Integer::sum);
-
2011๋ ์ ์ผ์ด๋ ๋ชจ๋ ํธ๋์ญ์ ์ ์ฐพ์ ๊ฐ์ ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ฆฌํ์์ค.
transactions.stream() .filter(transaction -> transaction.getYear() == 2011) .sorted(comparing(Transaction::getValue)) .collect(toList())
-
๊ฑฐ๋์๊ฐ ๊ทผ๋ฌดํ๋ ๋ชจ๋ ๋์๋ฅผ ์ค๋ณต ์์ด ๋์ดํ๋ผ.
List<String> cities = transaction.stream() .map(transaction -> transaction.getTrader().getCity()) .distinct() .collect(toSet());
-
์ผ์๋ธ๋ฆฌ์ง์ ๊ทผ๋ฌดํ๋ ๋ชจ๋ ๊ฑฐ๋์๋ฅผ ์ฐพ์์ ์ด๋ฆ์์ผ๋ก ์ ๋ ฌํ๋ผ
List<Trader> traders = transcations.stream() .map(Transaction::getTrader) .filter(trader -> trader.getCity().equals("Cambridge")) .distinct() .sorted(comparing(Trader::getName)) .collect(toList());
-
๋ชจ๋ ๊ฑฐ๋์์ ์ด๋ฆ์ ์ํ๋ฒณ์์ผ๋ก ์ ๋ ฌํด์ ๋ฐํํ๋ผ
String traderStr = transactions.stream() .map(transaction -> transaction.getTrader().getName()) .distinct() .sorted() .reduce("", (n1, n2)->n1+n2); //collect(joining())
-
๋ฐ๋ผ๋ ธ์ ๊ฑฐ๋์๊ฐ ์๋๊ฐ?
boolean milanBased = transaction.stream() .anyMatch(transaction -> transaction.getTrader().getCity().equals("Milan"))
-
์ผ์๋ธ๋ฆฌ์ง์ ๊ฑฐ์ฃผํ๋ ๊ฑฐ๋์์ ๋ชจ๋ ํธ๋์ญ์ ๊ฐ์ ์ถ๋ ฅํ์์ค
transactions.stream() .filter(t -> "Cambridge".equals(t.getTrader().getCity())) .map(Transaction::getValue) .forEach(System.out::println);
-
์ ์ฒด ํธ๋์ญ์ ์ค ์ต๋๊ฐ์ ?
Optional<Integer> hightestValue = transaction.stream() .map(Transaction::getValue) .reduce(Integer::max)
-
์ ์ฒด ํธ๋์ญ์ ์ค ์ต์๊ฐ์?
Optional<Transaction> smallestTransaction = transactions.stream() .min(comparing(Transaction::getValue))
๊ธฐ์กด ์คํธ๋ฆผ
int calories = menu.stream()
.map(Dish::getCalories)
.reduce(Integer::sum);->
int calories = menu.stream()
.map(Dish::getCalories)
.sum();์๋จ!!! why? ์คํธ๋ฆผ ์ ์์ ํ์์ Integer์ง๋ง ์ธํฐํ์ด์ค์๋ sum ๋ฉ์๋๊ฐ ์๋ค.
-> ๊ธฐ๋ณธํ ํนํ ์คํธ๋ฆผ ๋ฑ์ฅ
int calories = menu.stream()
.mapToInt(Dish::getCalories)
.sum(); //IntStream ์ธํฐํ์ด์ค์์ ์ ๊ณตํ๋ sum๋ฉ์๋ ์ด์ฉIntStream ์์ ๋ค์ Stream์ผ๋ก ๋์๊ฐ๋ ค๋ฉด?
Stream<Integer> stream = intStream.boxed();but ์์๊ฐ ์์ ๋ ๊ธฐ๋ณธ์ผ๋ก 0์ ๋ฐํํจ -> ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ์ ์์.
OptionalInt
OptionalInt maxCalories = menu.stream()
.mapToInt(Dish::getCalories)
.max();
int max = maxCalories.orElse(1);์ซ์ ๋ฒ์
ํน์ ๋ฒ์์ ์ซ์๋ฅผ ์ด์ฉํดํ๋ ์ํฉ
IntStream evenNumbers = IntStream.rangeClosed(1, 100)
.filter(n -> n % 2 == 0); //1 - 100 ๊น์ง ์ง์ ์คํธ๋ฆผ
system.out.println(evenNumbers.count());Stream<String> stream = Stream.of("Java 8", "Lambdas ", "In ", "Actions");
stream.map(String::toUpperCase).forEach(System.out::println);
Stream.empty(); //๋น ์คํธ๋ฆผ ๋ง๋ค๊ธฐ๋ฐฐ์ด์ผ ๋
int[] numbers = {2, 3, 5, 7, 11, 13};
int sum = Arrays.stream(numbers).sum(); //intstream ์์ฑ๋จํ์ผ์ผ ๋
long uniqueWords = 0;
try(Stream<String> lines =
Files.lines(Paths.get("data.txt"), Charset.defaultCharset())){
uniqueWords = lines.flatMap(line -> Arrays.stream(line.split(" ")))
.distinct()
.count();
}catch(IOException e){
}iterate
Stream.iterate(0, n -> n+2 )
.limit(10)
.forEach(System.out::println);
0
2
4
6
8
10
12
14
16
18iterate ๋ฌดํ ์คํธ๋ฆผ์ ๋ง๋ ๋ค
generate
Stream.generate(Math::random)
.limit(5)
.forEach(System.out::println);์๋ก์ด ๊ฐ์ ์์ฐํ๋ค.
iterate๋ generate ๋ชจ๋ limit๊ฐ ์์ผ๋ฉด ์ธ ๋ฐ์ด๋ ์ํ๊ฐ ๋จ. ๋ฌดํ...
IntSupplier fib = new IntSupplier(){
private int previous = 0;
private int current =1;
public int getAsInt(){
int oldPrevious = this.previous;
int nextValue = this.previous + this.current;
this.previous = this.current;
this.current = nextValue;
return oldPrevious;
}
};
IntStream.generate(fib).limit(10).forEach(System.out::println); //๊ณ์ฐ ์ค์์ fib ๊ฐ๋ณ ๊ฐ์ฒด์๊ธฐ์กด ์ฝ๋
Map<Currency, List<Transaction>> transactionsByCurrencies = new HashMap<>();
for(Transaction transaction : transactions){
Currency = transaction.getCurrencty();
List<Transaction> transactionsForCurrency = transactionsByCurrencies.get(currency);
if(transactionsForCurrency == null){
transactionsForCurrency.put(currencty, transactionsForCurrency);
}
transactionsForCurrency.add(transaction);
}stream
Map<Currency, List<Transaction>> transactionsByCurrencies = transactions.stream().collect(groupingBy(Transaction::getCurrency));ํจ์ํ ํ๋ก๊ทธ๋๋ฐ : '๋ฌด์'์ ์ป์์ง ์ง์ ๋ช ์ but ์ด๋ค ๋ฐฉ๋ฒ์ผ๋ก ์ป์์ง๋ ๋ ธ๊ด์ฌ
๋ฆฌ๋์ฑ ๊ธฐ๋ฅ์ ์ํํ๋ ์ปฌ๋ ํฐ
์ ์ฝ๋์์ ์คํธ๋ฆผ์ด ๊ฐ ํธ๋์ญ์ ์ ํ์ํ๊ณ currency๋ฅผ ์ถ์ถํ์ฌ group ํ๋ ๊ณผ์ ์ ์ง์ ๊ตฌํํ์ง ์์๋ ๋จ
๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ ๊ฒ toList()
List<Transaction> transactions = transactionsTream.collect(Collector.toList());์ปฌ๋ ํฐ๊ฐ ์ ๊ณตํ๋ ๊ธฐ๋ฅ
- ์คํธ๋ฆผ ์์๋ฅผ ํ๋์ ๊ฐ์ผ๋ก ๋ฆฌ๋์คํ๊ณ ์์ฝ
- ์์ ๊ทธ๋ฃนํ
- ์์ ๋ถํ
Collector.counting -> import static java.util.stream.Collector.*; ์ถ๊ฐ ํ -> count()
long howManyDishes = menu.stream().count();์ต๋๊ฐ๊ณผ ์ต์๊ฐ ๊ตฌํ๊ธฐ
Comparator<Dish> dishCaloriesComparator = Comparator.comparingInt(Dish::getCalories);
Optional<Dish> mostCaloriesDish = menu.stream()
.collect(maxBy(dishCaloriesComparator));์คํธ๋ฆผ์ ์๋ ๊ฐ์ฒด์ ์ซ์ ํ๋์ ํฉ๊ณ๋ ํ๊ท ๋ฑ์ ๋ฐํํ๋ ์ฐ์ฐ์ ๋ฆฌ๋์ฑ ๊ธฐ๋ฅ์ด ์ฌ์ฉ๋๋ ๊ฒ = ์์ฝ
์์ฝ ์ฐ์ฐ
Collectors.summingInt ํ์ฉ
int totalCalories = menu.stream().collect(summingInt(Dish::getCalories));์ด๊ธฐ๊ฐ 0์์ ์์ํด์ ๊ฐ์ฒด๋ฅผ getCalories ๋ก ๋ณํํ ๋ํ๋ค
average
double avgCalories = menu.stream().collect(averagingInt(Dish::getCalories));summarizing (์์ฝ๋ ์ ๋ณด๋ฅผ ๊ฐ์ฒด๋ก ๋ฐํ)
IntSummaryStatistics menuStatistics = menu.stream().collect(summarizingInt(Dish::getCalories));
IntSummaryStatistics {
count = 9, sum = 4300, min =120,
average = 477.777778, max = 800
}๋ฌธ์์ด ์ฐ๊ฒฐ
String shortMenu = menu.stream().map(Dish::getName).collect(joining());- joining ๋ฉ์๋๋ StringBuilder๋ฅผ ์ด์ฉํด์ ๋ฌธ์์ด์ ๋ง๋ค์ด์ค
String shortMenu = menu.stream().collect(joining());toString ์ฌ์ฉ์ map ์ฌ์ฉ ์ํด๋๋จ.
๊ตฌ๋ถ์๋ฅผ ๋ฃ๊ณ ์ถ๋ค๋ฉด?
String shortMenu = menu.stream().collect(joining(", "));- ๊ทธ๋ฅ ๋ฃ์ผ๋ฉด ๋จ
๋ฒ์ฉ ๋ฆฌ๋์ฑ ์์ฝ ์ฐ์ฐ
collector๋ฅผ ํ์ฉํ ๊ฒ๋ค์ reduce ๋ก ๋ค ๊ตฌํ ๊ฐ๋ฅ (ํธ๋ฆฌํจ ๋๋ฌธ์ collector ์ฌ์ฉ)
reducing
- ์ฒซ๋ฒ์งธ ์ธ์๋ ์ธ์๊ฐ ์์ ๋ ๋ฐํ๊ฐ
- ๋ณํ์
- ๊ณ์ฐ์
int totalCalories = menu.stream().collect(reducing(0, Dish::getCalories, (i, j) -> i + j));ํ๊ฐ์ ์ธ์๋ฅผ ๊ฐ์ง ๋๋?
Optional<Dish> mostCalorieDish = menu.stream().collect(reducing((d1, d2)-> d1.getCalories() > d2.getCalories() ? d1 : d2));์ธ์ collect, reducing์ ์ฌ์ฉํด์ผํ๋?
์๋ก์ด ๊ฐ์ฒด๋ฅผ ํ ๋นํ๋ฉด ์ฑ๋ฅ ์ ํ๊ฐ ์ผ์ด๋๋ฏ๋ก collect ์ฌ์ฉํ๋ ๊ฒ ๋ ์ข์
**์ฌ๋ฌ๊ฐ์ง ๋ฐฉ๋ฒ **
int totalCalories = menu.stream().collect(reducing(0, Dish::getCalories, Integer::sum));int totlaCalories = menu.stream().map(Dish::getCaloreis).reduce(Integer::sum).get();int totalCalories = menu.stream().mapToInt(Dish::getCalories).sum();์ํฉ์ ๋ฐ๋ผ์ ์ ํํ๋ฉด๋จ.
Map<Dish.Type, List<Dish>> dishesByType = menu.stream().collect(groupingBy(Dish::getType));์คํธ๋ฆผ -> ๋ถ๋ฅํจ์ -> ๊ทธ๋ฃนํ ๋งต์ ๋ถ๋ฅ
๋ค์์ค ๊ทธ๋ฃนํ
Map<Dish.Type, Map<CaloricLevel, List<Dish>> = dishesByTypeCaloricLevel =
menu.stream().collect(
groupingBy(Dish::getType, groupingBy(dish ->{
if(dish.getCalories() <= 400){
return CaloricLevel.DIET;
}else if(dish.getCalories() <= 700){
return CaloricLevel.NORMAL;
}else{
return CaloricLevel.FAT;
}
})));์๋ธ๊ทธ๋ฃน ๋ฐ์ดํฐ ์์ง
Map<Dish.Type, Long> typesCount = menu.stream()
.collect(groupingBy(Dish::getType, counting()))Map<Dish.Type, Optional<Dish>> mostCaloricByType =
menu.stream()
.collect(groupingBy(Dish::getType, maxBy(comparingInt(Dish::getCalories))))์ปฌ๋ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ค๋ฅธ ํ์์ ์ ์ฉํ๊ธฐ
Map<Dish.Type, Dish> mostcaloricByType = =
menu.stream()
.collect(groupingBy(Dish::getType, collectingAndThen(
maxBy(comparingInt(Dish::getCalories)), Optional::get)));๋ถํ ํจ์๋ผ ๋ถ๋ฆฌ๋ ํ๋ ๋์ผ์ดํธ๋ฅผ ๋ถ๋ฅ ํจ์๋ก ์ฌ์ฉํ๋ ํน์ํ ๊ทธ๋ฃนํ ๊ธฐ๋ฅ
- boolean ํ์์ ๋งต
Map<Boolean, List<Dish>> partitionedMenu = menu.stream().collect(partitioningBy(Dish::isVegeterian));{false = [pork, beef, chicken, prawns, salmon],
true = [french fries, rice, season fruit, pizza]}
List<Dish> vegetarianDishes = partitionedMenu.get(true); //true์ธ ๊ฐ์ ๋ชจ๋ ๋ฐํ
//==
List<Dish> vegetarianDishes = menu.stream().filter(Dish::isVegetarian).collect(toList());๋ถํ ์ ์ฅ์
๋ถํ ํจ์๊ฐ ๋ฐํํ๋ ์ฐธ, ๊ฑฐ์ง ๋ ๊ฐ์ง ์์์ ์คํธ๋ฆผ ๋ฆฌ์คํธ๋ฅผ ๋ชจ๋ ์ ์งํ๋ค๋ ๊ฒ์ด ๋ถํ
Map<Boolean, Map<Dish.Type, List<Dish>>> vegetarianDishesByType = menu.stream().collect(partitioningBy(Dish::isVegetarian, groupingBy(Dish::getType)));{false = {FISH=[prawns, salmon], MEAT=[pork, beef, chicken]},
true = {OTHER=[french fries, rice, season fruit, pizza]}};
๊ฐ์ฅ ์นผ๋ก๋ฆฌ๊ฐ ๋์ ์๋ฆฌ ์ฐพ์ ์
Map<Boolean, Dish> mostCaloricPartitionedByVegetarian =
menu.stream().collect(
partitioningBy(Dish::isvegetarian, collectingAndThen(
maxBy(comparingInt(Dish::getCalories)), Optional::get
)));{false=pork, true=pizza}
์ซ์๋ฅผ ์์์ ๋น์์๋ก ๋ถํ ํ๊ธฐ
public boolean isPrime(int candidate){
return Intstream.range(2, candidate) //1 ~ candidate - 1๊น์ง์ ์ ์์ฑ
.nonMatch(i -> candidate % i == 0); //๋๋ ์ ์์ผ๋ฉด ์ฐธ ๋ฐํ
}-> ๋ ์ฐ์๋ ์ค์ด๋ฉด?
public boolean isPrime(int candidate){
int candidateRoot = (int) Math.sqrt((double)candidate);
return IntStream.rangeClosed(2, candidateRoot)
.noneMatch(i -> candidate % i == 0);
}-> partitioningBy์ ํ์ฉํ๋ฉด?
public Map<Boolean, List<Integer>> partitionPrimes(int n){
return IntStream.rangeClosed(2, n).boxed()
.collect(
partitioningBy(candidate -> isPrime(candidate)));
}์ง๊ธ๊น์ง ๋ฐฐ์ด collector
| ํฉํ ๋ฆฌ ๋ฉ์๋ | ๋ฐํ ํ์ | ์ฌ์ฉ ์์ |
|---|---|---|
| toList | List | ์คํธ๋ฆผ์ ๋ชจ๋ ํญ๋ชฉ์ ๋ฆฌ์คํธ๋ก ์์ง |
| toSet | Set | ์คํธ๋ฆผ์ ๋ชจ๋ ํญ๋ชฉ์ ์ค๋ณต์ด ์๋ ์งํฉ์ผ๋ก ์์ง |
| toCollection | Collection | ์คํธ๋ฆผ์ ๋ชจ๋ ํญ๋ชฉ์ ๊ณต๊ธ์๊ฐ ์ ๊ณตํ๋ ์ปฌ๋ ์ ์ผ๋ก ์์งex) .collect(toCollection(), ArrayList::new); |
public interface Collector<T, A, R>{
Supplier<A> supplier();
BiConsumer<A, T> accumulator();
Function<A, R> finisher();
BinaryOperator<A> combiner();
Set<Characteristics> characteristics();
}- T๋ ์คํธ๋ฆผ ํญ๋ชฉ์ ์ ๋ค๋ฆญ
- A๋ ๋์ ์, ์์ง ๊ณผ์ ์์ ์ค๊ฐ ๊ฒฐ๊ณผ๋ฅผ ๋์ ํ๋ ๊ฐ์ฒด์ ํ์
- R์ ์์ง ์ฐ์ฐ ๊ฒฐ๊ณผ ๊ฐ์ฒด์ ํ์
**supplier ๋ฉ์๋ **: ์๋ก์ด ๊ฒฐ๊ณผ ์ปจํ ์ด๋ ๋ง๋ค๊ธฐ
supplier๋ ์์ง ๊ณผ์ ์์ ๋น ๋์ ์ ์ธ์คํด์ค๋ฅผ ๋ง๋๋ ํ๋ผ๋ฏธํฐ๊ฐ ์๋ ํจ์
public Supplier<List<T>> supplier(){
return () -> new ArrayList<T>(); //ArrayList::new;
}accumulator ๋ฉ์๋: ๊ฒฐ๊ณผ ์ปจํ ์ด๋์ ์์ ์ถ๊ฐํ๊ธฐ
๋ฆฌ๋์ฑ ์ฐ์ฐ์ ์ํํ๋ ํจ์๋ฅผ ๋ฐํ
public BiComsumer<List<T>, T>accumulator(){
return (list, item) -> list.add(item); //List::add
}**finisher ๋ฉ์๋ **: ์ต์ข ๋ณํ๊ฐ์ ๊ฒฐ๊ณผ ์ปจํ ์ด๋๋ก ์ ์ฉํ๊ธฐ
์คํธ๋ฆผ ํ์์ ๋๋ด๊ณ ๋์ ์ ๊ฐ์ฒด๋ฅผ ์ต์ข ๊ฒฐ๊ณผ๋ก ๋ณํํ๋ฉด์ ๋์ ๊ณผ์ ์ ๋๋ผ ๋ ํธ์ถํ ํจ์๋ฅผ ๋ฐํํด์ผํจ
public Function<List<T>, List<T>> finisher(){
return Function.identity();
}combiner ๋ฉ์๋ : ๋ ๊ฒฐ๊ณผ ์ปจํ ์ด๋ ๋ณํฉ
์์ฐจ ๋ฆฌ๋์ฑ ๊ณผ์ ์ ๋ ผ๋ฆฌ์ ์์
- A accumulator = collector.supplier().get();
- ์คํธ๋ฆผ์ ์์๊ฐ ๋จ์ ์๋๊ฐ? -> ์ - Collector.accumulator().accept(accumulator, next) -> 2๋ฒ ๋ค์ ์คํ
- R result = collector.finisher().apply(accumulator);
- return result;
public BinaryOperator<List<T>> combiner(){
return (list1, list2) =?{
list1.addAll(list2);
return list1;
}
}Characteristics
- unordered
- ์คํธ๋ฆผ ์์์ ๋ฐฉ๋ฌธ ์์๋ ๋์ ์์์ ์ํฅ์ ๋ฐ์ง ์์
- concurrent
- ๋ค์ค ์ค๋ ๋์์ accumulatorํจ์๋ฅผ ๋์์ ํธ์ถํ ์ ์์ผ๋ฉฐ ์ด ์ปฌ๋ ํฐ๋ ์คํธ๋ฆผ์ ๋ณ๋ ฌ ๋ฆฌ๋์ฑ์ ์ํํ ์ ์์.
- Identity_finish
- Finisher ๋ฉ์๋๊ฐ ๋ฐํํ๋ ํจ์๋ ๋จ์ํ identity๋ฅผ ์ ์ฉํ ๋ฟ์ด๋ฏ๋ก ์ด๋ฅผ ์๋ตํ ์ ์๋ค. ๋ฐ๋ผ์ ์ต์ข ๊ฒฐ๊ณผ๋ก ๋์ ์ ๊ฐ์ฒด๋ฅผ ๋ฐ๋ก ์ฌ์ฉํ ์ ์์
public class ToListCollector<T> implements Collector<T, List<T>, List<T>>{
@Override
public Supplier<List<T>> supplier(){ //์์ง ์ฐ์ฐ์ ์๋ฐ์
return ArrayList::new;
}
@Override
public BiComsumer<List<T>, T> accumulator(){ //ํ์ํ ํญ๋ชฉ์ ๋์ ํ๊ณ ๋ฐ๋ก ๋์ ์๋ฅผ ๊ณ ์นจ
return List::add;
}
@Override
public Function<List<T>, List<T>> finisher(){ //ํญ๋ฑ ํจ์
return Function.indentity();
}
@Oeverride
public BinaryOperator<List<T>> combiner(){ //๋ ๋ฒ์งธ ์ฝํ
์ธ ์ ํจ์ณ์ ์ฒซ ๋ฒ์งธ ๋์ ์๋ฅผ ๊ณ ์น๋ค.
return (list1, list2)->{
list1.addAll(list2);
return list1;
}
}
@Override
public Set<Characteristics> characteristics(){ //์ฝ๋ ํฐ์ ํ๋๊ทธ ์ค์
return Collections.unmodifiableSet(EnumSet.of(IDENTITY_FINISH, CONCURRENT));
}
}List<Dish> dishes = menuStream.collect(new ToListCollector<Dish>());๊ธฐ์กด ์ฝ๋
List<Dish> dishes = menuStream.collect(toList());๊ตฌํํ์ง ์๊ณ ๋ง๋ค๊ธฐ (IDENTITY_FINISH ์ผ๋)
List<Dish> dishes = menuStream.collect(
ArrayList::new, List::add, List::addAll);n์ดํ์ ์์ฐ์๋ฅผ ์์์ ๋น์์๋ก ๋ถ๋ฅํ๊ธฐ
public Map<Boolean, List<Integer>> partitionPrimes(int n){
return IntStream.rangeClosed(2, n).boxed()
.collect(partitioningBy(candidate -> isPrime(candidate)))
}์์๋ก๋ง ๋๋๊ธฐ
- Collector ํด๋์ค ์๊ทธ๋์ฒ ์ ์
public class PrimeNumbersCollector implements Collector<Integer, Map<Boolean, List<Integer>>, Map<Boolean, List<Integer>>>- ๋ฆฌ๋์ฑ ์ฐ์ฐ ๊ตฌํ
@Override
public BiConsumer<Map<Boolean, List<Integer>>, Integer> accumulator() {
return (Map<Boolean, List<Integer>> acc, Integer candidate)->{
acc.get(isPrime(acc.get(true), candidate))
.add(candidate);
};
}- ๋ณ๋ ฌ ์คํํ ์ ์๋ ์ปฌ๋ ํฐ ๋ง๋ค๊ธฐ
@Override
public BinaryOperator<Map<Boolean, List<Integer>>> combiner() {
return (Map<Boolean, List<Integer>> map1, Map<Boolean, List<Integer>> map2)->{
map1.get(true).addAll(map2.get(true));
map1.get(false).addAll(map2.get(false));
return map1;
};
}- finisher ๋ฉ์๋์ ์ปฌ๋ ํฐ์ characteristics ๋ฉ์๋
@Override
public Function<Map<Boolean, List<Integer>>, Map<Boolean, List<Integer>>> finisher() {
return Function.identity();
} @Override
public Set<Characteristics> characteristics() {
return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH));
}์ฐธ๊ณ
Java 8 in action

