将数字按质数与非质数分区
package streams;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.IntStream;
public class PrimeNumber {
public static boolean isPrime1(int num) {
int sqrtNum = (int) Math.sqrt(num);
return IntStream.rangeClosed(2, sqrtNum)
.noneMatch(i -> num % i == 0);
}
public static boolean isPrime2(List<Integer> primes, int num) {
int sqrtNum = (int) Math.sqrt(num);
return takeWhile(primes, i -> i <= sqrtNum)
.stream()
.noneMatch(i -> num % i == 0);
}
public static <A> List<A> takeWhile(List<A> list, Predicate<A> p) {
int i = 0;
for (A l : list) {
if (!p.test(l)) {
return list.subList(0, i);
}
i++;
}
return list;
}
}
实现一个收集器并测试性能
package streams;
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 java.util.stream.IntStream;
import static java.util.stream.Collector.Characteristics.IDENTITY_FINISH;
import static java.util.stream.Collectors.partitioningBy;
/**
* 第一步,定义Collector类的签名
*/
public class MyCollector implements Collector<Integer, Map<Boolean, List<Integer>>,
Map<Boolean, List<Integer>>> {
/**
* 第二步,实现规约过程
*
* @return
*/
@Override
public Supplier<Map<Boolean, List<Integer>>> supplier() {
return () -> new HashMap<Boolean, List<Integer>>() {{
put(true, new ArrayList<>());
put(false, new ArrayList<>());
}};
}
@Override
public BiConsumer<Map<Boolean, List<Integer>>, Integer> accumulator() {
return (Map<Boolean, List<Integer>> acc, Integer num) -> {
acc.get(PrimeNumber.isPrime2(acc.get(true), num))
.add(num);
};
}
/**
* 第三步,让并行器并行工作(如果可能)
*
* @return
*/
@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方法
*
* @return
*/
@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));
}
public static Map<Boolean, List<Integer>> partitionPrimes(int n) {
return IntStream.rangeClosed(2, n).boxed()
.collect(partitioningBy(i -> PrimeNumber.isPrime1(i)));
}
public static Map<Boolean, List<Integer>> partitionPrimesWithCustomCollector(int n) {
return IntStream.rangeClosed(2, n).boxed().collect(new MyCollector());
}
public static long testPerf (Function<Integer,Map<Boolean, List<Integer>>> adder, int n) {
long fast = Long.MAX_VALUE;
for (int i = 0; i < 10; i++) {
long start = System.nanoTime();
adder.apply(n);
long spendTime = (System.nanoTime() - start) / 1_000_000;
if (spendTime < fast)
fast = spendTime;
}
return fast;
}
public static void main(String[] args) {
System.out.println("Collector spend " +
testPerf(MyCollector::partitionPrimes, 1000_000) + " msecs ");
System.out.println("MyCollector spend " +
testPerf(MyCollector::partitionPrimesWithCustomCollector, 1000_000) + " msecs ");
}
}
比较自己实现的收集器与partitioningBy工厂方法创建的收集器的性能
在我的电脑
多次运行结果如下:
测试的次数不多,提升的性能大概在35%~40%之间