diff --git a/src/main/java/lambdasinaction/chap3/Sorting.java b/src/main/java/lambdasinaction/chap3/Sorting.java index 41acbe25..78fd1fdd 100644 --- a/src/main/java/lambdasinaction/chap3/Sorting.java +++ b/src/main/java/lambdasinaction/chap3/Sorting.java @@ -7,7 +7,7 @@ public class Sorting { public static void main(String...args){ - // 1 + // 1 构造需要排序的列表 List inventory = new ArrayList<>(); inventory.addAll(Arrays.asList(new Apple(80,"green"), new Apple(155, "green"), new Apple(120, "red"))); @@ -18,7 +18,7 @@ public static void main(String...args){ // reshuffling things a little inventory.set(1, new Apple(30, "green")); - // 2 + // 2 匿名函数方式 // [Apple{color='green', weight=30}, Apple{color='green', weight=80}, Apple{color='green', weight=155}] inventory.sort(new Comparator() { public int compare(Apple a1, Apple a2){ @@ -29,7 +29,7 @@ public int compare(Apple a1, Apple a2){ // reshuffling things a little inventory.set(1, new Apple(20, "red")); - // 3 + // 3 Lambda表达式方式 // [Apple{color='red', weight=20}, Apple{color='green', weight=30}, Apple{color='green', weight=155}] inventory.sort((a1, a2) -> a1.getWeight().compareTo(a2.getWeight())); System.out.println(inventory); @@ -37,7 +37,7 @@ public int compare(Apple a1, Apple a2){ // reshuffling things a little inventory.set(1, new Apple(10, "red")); - // 4 + // 4 方法引用方式 // [Apple{color='red', weight=10}, Apple{color='red', weight=20}, Apple{color='green', weight=155}] inventory.sort(comparing(Apple::getWeight)); System.out.println(inventory); diff --git a/src/main/java/lambdasinaction/chap4/IteratorOnce.java b/src/main/java/lambdasinaction/chap4/IteratorOnce.java new file mode 100644 index 00000000..621bc6a5 --- /dev/null +++ b/src/main/java/lambdasinaction/chap4/IteratorOnce.java @@ -0,0 +1,20 @@ +package lambdasinaction.chap4; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; + +/** + * 流只能消费一次 + * Created by qianqb on 16/9/28. + */ +public class IteratorOnce { + + public static void main(String[] args) { + List title = Arrays.asList("Java8","In","Action"); + Stream s = title.stream(); + s.forEach(System.out::println); + //已消费过,会抛异常 + s.forEach(System.out::println); + } +} diff --git a/src/main/java/lambdasinaction/chap5/PuttingIntoPractice.java b/src/main/java/lambdasinaction/chap5/PuttingIntoPractice.java index d0b13ae5..773374ea 100644 --- a/src/main/java/lambdasinaction/chap5/PuttingIntoPractice.java +++ b/src/main/java/lambdasinaction/chap5/PuttingIntoPractice.java @@ -7,8 +7,16 @@ import static java.util.Comparator.comparing; import static java.util.stream.Collectors.toList; +/** + * 实战代码 + */ public class PuttingIntoPractice{ - public static void main(String ...args){ + + + public static void main(String ...args){ + + //构建数据集 + Trader raoul = new Trader("Raoul", "Cambridge"); Trader mario = new Trader("Mario","Milan"); Trader alan = new Trader("Alan","Cambridge"); diff --git a/src/main/java/lambdasinaction/chap5/Reducing.java b/src/main/java/lambdasinaction/chap5/Reducing.java index 93aed73e..e1e1775c 100644 --- a/src/main/java/lambdasinaction/chap5/Reducing.java +++ b/src/main/java/lambdasinaction/chap5/Reducing.java @@ -6,6 +6,10 @@ import static lambdasinaction.chap4.Dish.menu; + +/** + * 归约 + */ public class Reducing{ public static void main(String...args){ diff --git a/src/main/java/lambdasinaction/chap5/Trader.java b/src/main/java/lambdasinaction/chap5/Trader.java index 7487a8c6..cb70052e 100644 --- a/src/main/java/lambdasinaction/chap5/Trader.java +++ b/src/main/java/lambdasinaction/chap5/Trader.java @@ -1,7 +1,13 @@ package lambdasinaction.chap5; + +/** + * 交易员 domain + */ public class Trader{ - + + //交易员姓名 private String name; + //交易员来自的城市 private String city; public Trader(String n, String c){ diff --git a/src/main/java/lambdasinaction/chap5/Transaction.java b/src/main/java/lambdasinaction/chap5/Transaction.java index 754e3839..debf1ffd 100644 --- a/src/main/java/lambdasinaction/chap5/Transaction.java +++ b/src/main/java/lambdasinaction/chap5/Transaction.java @@ -1,9 +1,15 @@ package lambdasinaction.chap5; +/** + * 一笔交易 + */ public class Transaction{ + //交易员 private Trader trader; + //交易年份 private int year; + //交易金额 private int value; public Transaction(Trader trader, int year, int value) diff --git a/src/main/java/lambdasinaction/chap5/quiz/NumberPair.java b/src/main/java/lambdasinaction/chap5/quiz/NumberPair.java new file mode 100644 index 00000000..61cabb52 --- /dev/null +++ b/src/main/java/lambdasinaction/chap5/quiz/NumberPair.java @@ -0,0 +1,41 @@ +package lambdasinaction.chap5.quiz; + +import java.util.Arrays; +import java.util.List; + +import static java.util.stream.Collectors.toList; + +/** + * Created by qianqb on 16/9/28. + * 返回所有数对 + */ +public class NumberPair { + + public static void main(String[] args) { + List number1 = Arrays.asList(1,2,3); + List number2 = Arrays.asList(3,4); + + List pairs = + number1.stream().flatMap(i-> number2.stream().map(j -> new int[]{i,j})) + .collect(toList()); + + pairs.stream().forEach(array-> System.out.println(array[0]+"-" + array[1] )); + + + pairs.stream().filter(array->(array[0]+array[1])%3==0 ).forEach(array->System.out.println(array[0]+"-" + array[1])); + } + + public void better(){ + List number1 = Arrays.asList(1,2,3); + List number2 = Arrays.asList(3,4); + + List pairs = + number1.stream() + .flatMap(i-> number2.stream().filter(j->(i+j)%3==0) + .map(j -> new int []{i,j})) + .collect(toList()); + + + + } +} diff --git a/src/main/java/lambdasinaction/chap5/quiz/SquareArray.java b/src/main/java/lambdasinaction/chap5/quiz/SquareArray.java new file mode 100644 index 00000000..13adf22c --- /dev/null +++ b/src/main/java/lambdasinaction/chap5/quiz/SquareArray.java @@ -0,0 +1,20 @@ +package lambdasinaction.chap5.quiz; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Created by qianqb on 16/9/28. + * 返回平方 + */ +public class SquareArray { + + public static void main(String[] args) { + Integer[] iArray = {1,2,3,4}; + Stream iStream = Arrays.stream(iArray); + List squares = iStream.map(x->x*x).collect(Collectors.toList()); + squares.stream().forEach(e-> System.out.println(e)); + } +} diff --git a/src/main/java/lambdasinaction/chap6/Dish.java b/src/main/java/lambdasinaction/chap6/Dish.java index a353f1bc..3f470b95 100644 --- a/src/main/java/lambdasinaction/chap6/Dish.java +++ b/src/main/java/lambdasinaction/chap6/Dish.java @@ -2,11 +2,18 @@ import java.util.*; +/** + * 菜类 + */ public class Dish { + //菜名 private final String name; + //是否蔬菜 private final boolean vegetarian; + //热量 private final int calories; + //类型 private final Type type; public Dish(String name, boolean vegetarian, int calories, Type type) { diff --git a/src/main/java/lambdasinaction/chap6/Grouping.java b/src/main/java/lambdasinaction/chap6/Grouping.java index bedb3470..c57dc4ed 100644 --- a/src/main/java/lambdasinaction/chap6/Grouping.java +++ b/src/main/java/lambdasinaction/chap6/Grouping.java @@ -20,10 +20,18 @@ public static void main(String ... args) { System.out.println("Caloric levels by type: " + caloricLevelsByType()); } + /** + * 按菜类型分组 + * @return + */ private static Map> groupDishesByType() { return menu.stream().collect(groupingBy(Dish::getType)); } + /** + * 按热量等级分组 + * @return + */ private static Map> groupDishesByCaloricLevel() { return menu.stream().collect( groupingBy(dish -> { @@ -33,6 +41,10 @@ private static Map> groupDishesByCaloricLevel() { } )); } + /** + * 先按菜类型分组,再按热量细分 + * @return + */ private static Map>> groupDishedByTypeAndCaloricLevel() { return menu.stream().collect( groupingBy(Dish::getType, @@ -45,10 +57,15 @@ private static Map>> groupDishedByTypeAn ); } + //各个菜分组的数量 private static Map countDishesInGroups() { return menu.stream().collect(groupingBy(Dish::getType, counting())); } + /** + * 每个类型热量最好的菜品 + * @return + */ private static Map> mostCaloricDishesByType() { return menu.stream().collect( groupingBy(Dish::getType, diff --git a/src/main/java/lambdasinaction/chap6/PartitionPrimeNumbers.java b/src/main/java/lambdasinaction/chap6/PartitionPrimeNumbers.java index 5122a6a3..7a3146d2 100644 --- a/src/main/java/lambdasinaction/chap6/PartitionPrimeNumbers.java +++ b/src/main/java/lambdasinaction/chap6/PartitionPrimeNumbers.java @@ -7,6 +7,9 @@ import static java.util.stream.Collectors.*; import static java.util.stream.Collector.Characteristics.*; +/** + * 质数分区 + */ public class PartitionPrimeNumbers { public static void main(String ... args) { @@ -15,17 +18,33 @@ public static void main(String ... args) { } + /** + * 质数分区 + * @param n + * @return + */ public static Map> partitionPrimes(int n) { + //生成2~n的数字,按质数分区 return IntStream.rangeClosed(2, n).boxed() .collect(partitioningBy(candidate -> isPrime(candidate))); } + /** + * 判断数字是否是质数的算法, 可以被2-质数平方根之间的值整除的就不是质数 + * @param candidate + * @return + */ public static boolean isPrime(int candidate) { return IntStream.rangeClosed(2, candidate-1) .limit((long) Math.floor(Math.sqrt((double) candidate)) - 1) .noneMatch(i -> candidate % i == 0); } + /** + * 使用自定义收集器分区质数 + * @param n + * @return + */ public static Map> partitionPrimesWithCustomCollector(int n) { return IntStream.rangeClosed(2, n).boxed().collect(new PrimeNumbersCollector()); } @@ -47,6 +66,9 @@ public static List takeWhile(List list, Predicate p) { return list; } + /** + * 自定义质数收集器 + */ public static class PrimeNumbersCollector implements Collector>, Map>> { diff --git a/src/main/java/lambdasinaction/chap7/ForkJoinSumCalculator.java b/src/main/java/lambdasinaction/chap7/ForkJoinSumCalculator.java index 8f74a90a..a7dd0e4e 100644 --- a/src/main/java/lambdasinaction/chap7/ForkJoinSumCalculator.java +++ b/src/main/java/lambdasinaction/chap7/ForkJoinSumCalculator.java @@ -6,38 +6,60 @@ import static lambdasinaction.chap7.ParallelStreamsHarness.FORK_JOIN_POOL; +/** + * 一个Fork/join框架示例,继承RecursiveTask来创建可以用于分支/合并框架的任务 + */ public class ForkJoinSumCalculator extends RecursiveTask { + //不再将任务分解为子任务的数组大小 public static final long THRESHOLD = 10_000; + //要求和的数组 private final long[] numbers; + //子任务处理的数组的其实和终止位置 private final int start; private final int end; + //公共构造函数用于创建主任务 public ForkJoinSumCalculator(long[] numbers) { this(numbers, 0, numbers.length); } + //私有构造函数用于以递归方式为主任务创建子任务 private ForkJoinSumCalculator(long[] numbers, int start, int end) { this.numbers = numbers; this.start = start; this.end = end; } + /** + * 覆盖RecursiveTask抽象方法, + * @return + */ @Override protected Long compute() { int length = end - start; if (length <= THRESHOLD) { return computeSequentially(); } + //创建一个子任务来为数组的前一半求和 ForkJoinSumCalculator leftTask = new ForkJoinSumCalculator(numbers, start, start + length/2); + //利用另一个ForkJoinPool线程异步执行新创建的子任务 leftTask.fork(); + //创建一个任务为数组的后一半求和 ForkJoinSumCalculator rightTask = new ForkJoinSumCalculator(numbers, start + length/2, end); + //同步执行第二个子任务,有可能允许进一步递归划分 Long rightResult = rightTask.compute(); + //读取第一个子任务的结果,如果尚未完成久等待 Long leftResult = leftTask.join(); + //该任务的结果是两个子任务的组合 return leftResult + rightResult; } + /** + * 顺序计算 + * @return + */ private long computeSequentially() { long sum = 0; for (int i = start; i < end; i++) { diff --git a/src/main/java/lambdasinaction/chap7/ParallelStreams.java b/src/main/java/lambdasinaction/chap7/ParallelStreams.java index e8b2a520..dfb83f73 100644 --- a/src/main/java/lambdasinaction/chap7/ParallelStreams.java +++ b/src/main/java/lambdasinaction/chap7/ParallelStreams.java @@ -4,6 +4,11 @@ public class ParallelStreams { + /** + * 1~n的数字求和 + * @param n + * @return + */ public static long iterativeSum(long n) { long result = 0; for (long i = 0; i <= n; i++) { @@ -16,6 +21,11 @@ public static long sequentialSum(long n) { return Stream.iterate(1L, i -> i + 1).limit(n).reduce(Long::sum).get(); } + /** + * 并行化 + * @param n + * @return + */ public static long parallelSum(long n) { return Stream.iterate(1L, i -> i + 1).limit(n).parallel().reduce(Long::sum).get(); } @@ -47,4 +57,21 @@ public void add(long value) { total += value; } } + + public static void main(String[] args) { + Long num = 10000l; + System.out.println(iterativeSum(num)); + System.out.println(sequentialSum(num)); + System.out.println(parallelSum(num)); + System.out.println(rangedSum(num)); + System.out.println(parallelRangedSum(num)); + System.out.println(sideEffectSum(num)); + System.out.println(sideEffectParallelSum(num)); + + //系统可用核数 + System.out.println(Runtime.getRuntime().availableProcessors()); + //改变并行线程池大小 + System.setProperty("jav.util.concurrent.ForkJoinPool.common.parallelism","12"); + + } } diff --git a/src/main/java/lambdasinaction/chap7/ParallelStreamsHarness.java b/src/main/java/lambdasinaction/chap7/ParallelStreamsHarness.java index 7d53c86f..c24ee8f2 100644 --- a/src/main/java/lambdasinaction/chap7/ParallelStreamsHarness.java +++ b/src/main/java/lambdasinaction/chap7/ParallelStreamsHarness.java @@ -18,6 +18,14 @@ public static void main(String[] args) { System.out.println("SideEffect prallel sum done in: " + measurePerf(ParallelStreams::sideEffectParallelSum, 10_000_000L) + " msecs" ); } + /** + * 测试合计性能 + * @param f + * @param input + * @param + * @param + * @return + */ public static long measurePerf(Function f, T input) { long fastest = Long.MAX_VALUE; for (int i = 0; i < 10; i++) { diff --git a/src/main/java/lambdasinaction/chap7/WordCount.java b/src/main/java/lambdasinaction/chap7/WordCount.java index 13ccce52..ba844c0e 100644 --- a/src/main/java/lambdasinaction/chap7/WordCount.java +++ b/src/main/java/lambdasinaction/chap7/WordCount.java @@ -4,8 +4,12 @@ import java.util.function.*; import java.util.stream.*; +/** + * 实现自己的spliterator,统计单词示例 + */ public class WordCount { + public static final String SENTENCE = " Nel mezzo del cammin di nostra vita " + "mi ritrovai in una selva oscura" + @@ -16,6 +20,11 @@ public static void main(String[] args) { System.out.println("Found " + countWords(SENTENCE) + " words"); } + /** + * 遍历以统计单词个数 + * @param s + * @return + */ public static int countWordsIteratively(String s) { int counter = 0; boolean lastSpace = true; @@ -30,6 +39,11 @@ public static int countWordsIteratively(String s) { return counter; } + /** + * 使用自定义spliterator统计单词个数 + * @param s + * @return + */ public static int countWords(String s) { //Stream stream = IntStream.range(0, s.length()) // .mapToObj(SENTENCE::charAt).parallel(); @@ -46,6 +60,10 @@ private static int countWords(Stream stream) { return wordCounter.getCounter(); } + + /** + * 用来在遍历Character流式计数的类 + */ private static class WordCounter { private final int counter; private final boolean lastSpace; @@ -55,6 +73,11 @@ public WordCounter(int counter, boolean lastSpace) { this.lastSpace = lastSpace; } + /** + * 上一个字符是空格,而当前遍历的字符不是空格时,将单词计数器加一 + * @param c + * @return + */ public WordCounter accumulate(Character c) { if (Character.isWhitespace(c)) { return lastSpace ? this : new WordCounter(counter, true); @@ -63,6 +86,11 @@ public WordCounter accumulate(Character c) { } } + /** + * 合并两个WordCounter,把其计数器加起来 + * @param wordCounter + * @return + */ public WordCounter combine(WordCounter wordCounter) { return new WordCounter(counter + wordCounter.counter, wordCounter.lastSpace); } @@ -72,6 +100,10 @@ public int getCounter() { } } + + /** + * String只能在词尾拆开。 + */ private static class WordCounterSpliterator implements Spliterator { private final String string; @@ -81,6 +113,11 @@ private WordCounterSpliterator(String string) { this.string = string; } + /** + * 如果还有字符要处理,则返回true + * @param action + * @return + */ @Override public boolean tryAdvance(Consumer action) { action.accept(string.charAt(currentChar++)); @@ -89,13 +126,19 @@ public boolean tryAdvance(Consumer action) { @Override public Spliterator trySplit() { + int currentSize = string.length() - currentChar; + //返回null表示要解析的String以机构足够小,可以书序处理 if (currentSize < 10) { return null; } + //将试探拆分位置设定为要解析的String的中间 for (int splitPos = currentSize / 2 + currentChar; splitPos < string.length(); splitPos++) { + //让拆分位置前进直到下一个空格 if (Character.isWhitespace(string.charAt(splitPos))) { + //创建一个新WordCounterSpliterator来解析String从开始到拆分位置的 部分 Spliterator spliterator = new WordCounterSpliterator(string.substring(currentChar, splitPos)); + //将这个WordCounterSpliterator的起始位置设为拆分位置 currentChar = splitPos; return spliterator; }