Esempi di collector e custom collector
This commit is contained in:
@@ -0,0 +1,56 @@
|
|||||||
|
package org.gym.fp.moderjava;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.BinaryOperator;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collector;
|
||||||
|
|
||||||
|
import static java.util.stream.Collector.Characteristics.IDENTITY_FINISH;
|
||||||
|
|
||||||
|
public class PrimeNumbersCollector implements Collector<Integer, Map<Boolean, List<Integer>>, Map<Boolean, List<Integer>>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Supplier<Map<Boolean, List<Integer>>> supplier() {
|
||||||
|
return () -> new HashMap<>() {{
|
||||||
|
put(true, new ArrayList<>());
|
||||||
|
put(false, new ArrayList<>());
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@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(IDENTITY_FINISH));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isPrime(List<Integer> primes, int candidate) {
|
||||||
|
int candidateRoot = (int) Math.sqrt(candidate);
|
||||||
|
return primes.stream()
|
||||||
|
.takeWhile(i -> i <= candidateRoot)
|
||||||
|
.noneMatch(i -> candidate % i == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -278,6 +278,43 @@ public class StreamTest {
|
|||||||
})));
|
})));
|
||||||
out.println(dishesByTypeCaloricLevel);
|
out.println(dishesByTypeCaloricLevel);
|
||||||
out.println("----------------------------------------");
|
out.println("----------------------------------------");
|
||||||
|
Map<Boolean, List<Dish>> partitionedMenu = menu.stream().collect(partitioningBy(Dish::isVegetarian));
|
||||||
|
out.println(partitionedMenu);
|
||||||
|
out.println("----------------------------------------");
|
||||||
|
Map<Boolean, Map<Dish.Type, List<Dish>>> vegetarianDishesByType =
|
||||||
|
menu.stream().collect(partitioningBy(Dish::isVegetarian, groupingBy(Dish::getType)));
|
||||||
|
out.println(vegetarianDishesByType);
|
||||||
|
out.println("----------------------------------------");
|
||||||
|
Map<Boolean, Dish> mostCaloricPartitionedByVegetarian =
|
||||||
|
menu.stream()
|
||||||
|
.collect(partitioningBy(Dish::isVegetarian,
|
||||||
|
collectingAndThen(maxBy(comparingInt(Dish::getCalories)), Optional::get)));
|
||||||
|
out.println(mostCaloricPartitionedByVegetarian);
|
||||||
|
out.println("----------------------------------------");
|
||||||
|
out.println(partitionPrimes(100));
|
||||||
|
out.println("----------------------------------------");
|
||||||
|
List<Dish> dishes = menu.stream()
|
||||||
|
.filter(Dish::isVegetarian)
|
||||||
|
.collect(new ToListCollector<>());
|
||||||
|
out.println(dishes);
|
||||||
|
out.println("----------------------------------------");
|
||||||
|
out.println(partitionPrimesWithCustomCollector(100));
|
||||||
|
out.println("----------------------------------------");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<Boolean, List<Integer>> partitionPrimes(int n) {
|
||||||
|
return IntStream.rangeClosed(2, n).boxed()
|
||||||
|
.collect(partitioningBy(candidate -> isPrime(candidate)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isPrime(int candidate) {
|
||||||
|
return IntStream.rangeClosed(2, candidate - 1)
|
||||||
|
.limit((long) Math.floor(Math.sqrt(candidate)) - 1)
|
||||||
|
.noneMatch(i -> candidate % i == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<Boolean, List<Integer>> partitionPrimesWithCustomCollector(int n) {
|
||||||
|
return IntStream.rangeClosed(2, n).boxed().collect(new PrimeNumbersCollector());
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CaloricLevel {DIET, NORMAL, FAT}
|
enum CaloricLevel {DIET, NORMAL, FAT}
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package org.gym.fp.moderjava;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.BinaryOperator;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collector;
|
||||||
|
|
||||||
|
import static java.util.stream.Collector.Characteristics.CONCURRENT;
|
||||||
|
import static java.util.stream.Collector.Characteristics.IDENTITY_FINISH;
|
||||||
|
|
||||||
|
// Collector<T, A, R> =>
|
||||||
|
// T = tipo generico degli elementi nello stream
|
||||||
|
// A = tipo dell'accumulatore, risultato parziale della riduzione
|
||||||
|
// R = tipo dell'oggetto risultato dall'operazione
|
||||||
|
public class ToListCollector<T> implements Collector<T, List<T>, List<T>> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return l'accumulatore vuoto
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Supplier<List<T>> supplier() {
|
||||||
|
return ArrayList::new;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return la funzione che accumula gli elementi T in A
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public BiConsumer<List<T>, T> accumulator() {
|
||||||
|
return List::add;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Questo metodo è invocato per combinare gli accumulatori
|
||||||
|
* elaborati da diversi sotto-stream
|
||||||
|
*
|
||||||
|
* @return la combinazione degli accumulatori
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public BinaryOperator<List<T>> combiner() {
|
||||||
|
return (list1, list2) -> {
|
||||||
|
list1.addAll(list2);
|
||||||
|
return list1;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Questo metodo viene invocato al termine del processo
|
||||||
|
* di accumulazione degli elementi dello {@link java.util.stream.Stream}
|
||||||
|
*
|
||||||
|
* @return la funzione che trasforma A in R
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Function<List<T>, List<T>> finisher() {
|
||||||
|
return Function.identity();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return insieme dei comportamenti che il collector deve assumere
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Set<Characteristics> characteristics() {
|
||||||
|
return Collections.unmodifiableSet(EnumSet.of(IDENTITY_FINISH, CONCURRENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user