Java实战-学习笔记

 

================================================Chapter-5 使用流
//外部迭代基础版
List<Dish> vegetarianDishes = new Arraylist<>();
for (Dish d:menu){if (d.isvegetarian()){vegetarianDishes.add(d)}}
===> //method of lambda
import static java.util.stream.Collectors.toList;
List<Dish> vegetarianDishes = menu.stream().filter(Dish::isvegetarian).collect(toList());

//5.1.2 筛选各异的元素(.distinct())
List<Integer> numbers = Arrays.asList(1,2,4,5,6,18);
numbers.stream().filter(i->i%2==0).distinct().forEach(System.out::println);

//5.1.3 截短流 (.limit(n))
List<Dish> dishes = menu.stream().filter(d->d.getCalories()>300).limit(3).collect(toList());

//5.1.4 跳过元素 (.skip(n))
List<Dish> dishes = menu.stream().filter(d->d.getCalories()>300).skip(2).collect(toList());

//5.2 映射 Map&flatMap
//5.2.1 对流中每一个元素应用函数(.map())
List<Dish> dishes = menu.stream().map(Dish::getName).collect(toList());
List<String> words = Arrays.asList("Java 8","Lambdas","In","Action");
List<String> wordLengths = words.stream().map(String::length).collect(toList());
===>lambdas
List<Integer> dishNameLengths = menu.stream().map(Dish::getName).map(String::length).collect(toList());

//5.2.2 流的扁平化 (应用flatmap合并流)
List<String> a = Arrays.asList("hello","word");
a.stream().map(word->word.split("")).distinct().collect(toList()); //此处hello和word被拆分为2个流进行处理并输出
===>
String[] arrayofwors = {"goodbye","world"};
Stream<String> streamOfwords = Arrays.stream(arrayofwors);
a.stream().Map(w->w.split("")).Map(Arrays::stream).distinct().collect(toList());
===>//并流操作 (.flatMap())
List<String> uniqueCharacters = 
a.stream().Map(w->w.split("")).flatMap(Arrays::stream).distinct().collect(Collectiors.toList());

//映射:n^2
List<Integer> numbers = Arrays.asList(1,2,3,4,5,6);
List<Integer> squares = numbers.stream().map(n->n*n).collect(toList());
//映射:Multiple 数组
List<Integer> numbers1 = Arrays.asList(1,2,3);
List<Integer> numbers2 = Arrays.asList(3,4);
List<int[]> pairs = 
numbers1.stream().flatMap(i->numbers2.stream().filter(j->(i+j)%3==0).map(j->new int[](i,j))).colect(toList());

//5.3 查找和匹配
allMatch,anyMatch,noneMatch,findFirst,findAny
//5.3.1 检查任一一个是否匹配:anyMatch
if(menu.stream().anyMatch(Dish::isVegetarian)){
	System.out.println("there is one Vegetarian at least");
}
//5.3.2 检查是否完全匹配: allMatch
boolean isHealthy = menu.stream().allMatch(d->d.getCalories()<1000);
//anyMatch<==>noneMatch:检查是否完全不匹配
boolean isHealthy = menu.stream().noneMatch(d->d.getCalories()>=1000);

//5.3.3 查找元素: findAny
Optional<Dish> dish = menu.stream().filter(Dish:isvegetarian).findAny();

//Optional<T>类
isPresent()							True&False 值是否存在
ifPresent(Consumer<T> block)		若值存在则执行代码块
T get()								值存在则返回值
T orElse(T other)					值存在则返回值,不存在返回默认值
menu.stream().filter(Dish::isvegetarian).findAny().ifPresent(d->System.out.println(d.getName()))

//5.3.4 查找第一个元素: findFirst
List<Integer> someNumbers = Arrays.asList(1,2,3,4,5);
Optional<Integer> firstSquareDivisibleByThree = someNumbers.stream().Map(x->x*x).filter(x->x%3==0).findFirst();

//5.4 归约: reduce

//5.4.1 元素求和 sum
public class cumsum{
	public static void main(String[] args){
		List<Integer> a = Arrays.asList(1,2,4,5,6,18);
		int sum=1;
		for (int i:a){sum+=i;System.out.println(sum);}
		System.out.println("*******RESULT*******");
		System.out.println(sum);
	}
}
===>cumsum
int sum = numbers.stream().reduce(0,(a,b)->a+b);
===>cumprod
int product=numbers.stream().reduce(1,(a,b)->a*b)
===>
int sum = numbers.stream().reduce(0,Integer::sum)

//5.4.2 最大值和最小值 Max & Min
Optional<Integer> max = numbers.stream().reduce(Integer::max);
Optional<Integer> min = numbers.stream().reduce(Integer::min);

//example:count(dishes_of_menu)
int count = menu.stream().map(d->1).reduce(0,(a,b)->a+b);
long count = menu.stream().count();

##使用并行流计算
int sum = numbers.parallelStream().reduce(0,Integer::sum);


//5.5 付诸实践
1) 找出2011年发生的所有交易,并且按照交易额排序(从低到高)
2) 交易员都在哪些不同城市工作过
3) 查找所有来自于剑桥的交易员,并且按照姓名排序
4) 返回所有交易员的姓名字符串,按字母排序
5) 有没有交易员是在米兰工作过?
6) 打印生活在剑桥的交易员所有交易额。
7) 所有交易中,最高的交易额是多少?
8) 找到交易额的最小的交易。
//5.5.1
public class trader {
	private final String name;
	private final String city;
	public trader(String n , String c){this.name=n;this.city=c;}
	public String getname(){return this.name;}
	public String getcity(){return this.city;}
	public String toString(){return "Trader: "+this.name+" in "+this.city;}
}
public class transaction{
	private final trader trader;
	private final int year;
	private final int value;
	public transaction(trader trader,int year,int value){
		this.trader=trader;
		this.year=year;
		this.value=value;
	}
	public trader gettrader(){return this.trader;}
	public int getyear(){return this.year;}
	public int getvalue(){return this.value;}
	public String toString(){return "{"+this.trader+", "+"year: "+this.year+", "+"value: "+this.value+"}";}
}
=============> method_1
public class tes{
	public static void main(String[] args){
		trader jack=new trader("jack","shanghai");
		trader mario=new trader("mario","Tokyo");
		trader alan=new trader("alan","new york");
		trader zieox=new trader("zieox","shanghai");
		List<transaction> trans=Arrays.asList(
			new transaction(zieox,2011,300),
			new transaction(zieox,2015,1800),
			new transaction(mario,2011,600),
			new transaction(mario,2015,1300),
			new transaction(jack,2011,1333),
			new transaction(alan,2011,100),
			new transaction(alan,2015,996)
		);
		//1. year=2011 and sum(交易额)
		int sum=0;
		for(transaction i:trans){if(i.getyear==2011){System.out.println(i);sum+=i.getvalue();} else continue}
		System.out.println(sum);	
	}
}

//5.5.2 lambda==>
//1.找出2011年发生的所有交易,并且按照交易额排序(从低到高)
===>
import static java.util.stream.Collectors.toList;
List<Transaction> tr2011 = trans.stream()
.filter(transaction ->transaction.getYear() == 2011)
.sorted(Comparator.comparing(Transaction::getValue))
.collect(toList())

//2. 交易员都在哪些不同城市工作过
===>
List<String> cities=trans.stream()
.map(transaction->transaction.gettrader().getcity())
.distinct()
.collect(toList());
//OR
Set<String> cities=trans.stream()
.map(transaction->transaction.gettrader().getcity())
.collect(toSet());

//3. 查找所有来自于shanghai的交易员,并且按照姓名排序
List<trader> traders=trans.stream()
				.map(transaction::gettrader)
				.filter(trader ->trader.getcity().equals("shanghai"))
				.distinct()
				.sorted(Comparator.comparing(trader::getname))
				.collect(toList());

//4. 返回所有交易员的姓名字符串,按字母排序
String traderStr=trans.stream()
.map(transaction->transaction.gettrader().getname())
.distinct()
.sorted()
.reduce("",(n1,n2)->n1+n2);

//OR
String traderStr=trans.stream()
.map(transaction->transaction.gettrader().getname())
.distinct()
.sorted()
.collect(joining());

//5. 有没有交易员是在米兰工作过?
boolean milanBased=trans.stream()
.anyMatch(transaction.gettrader().getcity().equals("milan"));

//6. 打印生活在shanghai的交易员所有交易额。
trans.stream()
.filter(t->"shanghai".equals(t.gettrader().getcity()))
.map(transaction::getvalue)
.forEach(System.out::println);

//7. 所有交易中,最高的交易额是多少?
Optional<Integer> highestValue=trans.stream()
.map(transaction::getvalue)
.reduce(Integer::max);

//8. 找到交易额的最小的交易。
Optional<transaction> smallesttransaction=trans.stream()
.reduce((t1,t2)->t1.getvalue()<t2.getvalue() ? t1:t2);

//or
Optional<transaction> smallesttransaction=trans.stream().min(comparing(transaction::getvalue));


//5.6 数值流
int calories = menu.stream().map(Dish::getCalories).reduce(0,Integer::sum);
int calories = menu.stream().map(Dish::getCalories).sum();

//5.6.1 原始类型流特化
1. 映射到数值流 mapToInt,mapToDouble,mapToLong
===>
int calories = menu.stream().mapToInt(Dish::getCalories).sum();
2. 转换回对象流 IntStream
===>
IntStream intStream = menu.Stream().mapToInt(Dish::getCalories);
Stream<Integer> stream = intStream.boxed();
3. 默认值 OptionalInt,OptionalDouble,OptionalLong
OptionalInt maxCalories = menu.Stream().mapToInt(Dish::getCalories).max(); //计算stream中的最大卡路里
int max = maxCalories.orElse(1);

//5.6.2 数值范围 range,rangeClosed,(IntStream,LongStream)
//实例:计算[1,100]中的偶数
IntStream evenNumbers = IntStream.rangeClosed(1,100).filter(n->n%2==0);
System.out.println(evenNumbers.count());


//5.6.3数值流应用:勾股数 a^2+b^2=c^2
1. 勾股数
2. 表示三元数
3. 筛选成立的组合
filter(b->Math.sqrt(a*a+b*b)%1==0)
4. 生成三元组
stream.filter(b->Math.sqrt(a*a+b*b)%1==0).map(b->new int[]{a,b,(int) Math.sqrt(a*a+b*b)});
5. 生成b值
IntStream.rangeClosed(1,100).filter(b->Math.sqrt(a*a+b*b)%1==0).boxed().map(b->new int[]{a,b,(int) Math.sqrt(a*a+b*b)});
===>
IntStream.rangeClosed(1,100).filter(b->Math.sqrt(a*a+b*b)%1==0).mapToObj(b->new int[]{a,b,(int) Math.sqrt(a*a+b*b)})
6. 生成值
===>
Stream<int[]> pythagoreanTriples = IntStream.rangeClosed(1,100).boxed()
.flatMap(a-> Math.sqrt(a*a+b*b)%1==0)
.mapToObj(b-> new int[]{a,b,(int)Math.sqrt(a*a+b*b)});

7. 运行代码
pythagoreanTriples.limit(5).forEach(t->System.out.println(t[0]+", "+t[1]+", "+t[2]));


8. ===>
Stream<double[]> pythagoreanTriples2 = IntStream.rangeClosed(1,100).boxed()
.flatMap(a->IntStream.rangeClosed(a,100).mapToObj(b->new double[]{a,b,Math.sqrt(a*a+b*b)}).filter(t->t[2]%1==0));

----------------------------------------
##python 实现 //非并行计算,未去重
def trs(a,b):
   for i in range(a,b):
      for j in range(a,b):
	     if Math.sqrt(i*i+j*j)%1==0 and i<>j:
		    print("i: "+str(i)+" j: "+j+"---> "+str(math.sqrt(i*i+j*j)))
//or
trs=[(i,j,i*i+j*j) for i in range(100) for j in range(100) if math.sqrt(i*i+j*j)%1==0]
----------------------------------------

//5.7 构建流
//5.7.1 由值创建流
Stream<String> stream = Stream.of("Java8"," Lambda ","in ","action ");
Stream.map(String::toUpperCase).forEach(System.out::println);
Stream<String> emptyStream = Stream.empty();//make a empty stream

//5.7.2 由数组创建流
in[] numbers = {2,3,5,7,12,221,122,32};
int sum=Arrays.stream(numbers).sum();

// 5.7.3 由文件创建流
import java.nio.file.Files;
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){}

//5.7.4 由函数生成流:创建无限流
Stream.API 提供了两个静态方法从函数生成流:Stream.iterator和Stream.gengerate (both can create limitness stream)

1. 迭代
Stream.iterate(0,n->n+2).limit(10).forEach(System.out::println);
//实例:fb数列
Stream.iterate(new int[]{0,1},t->new int[]{t[1],t[0]+t[1]}).limit(20).forEach(t->System.out.println("("+t[0]+","+t[1]+")"));
Stream.iterate(new int[]{0,1},t->new int[]{t[1],t[0]+t[1]}).limit(10).map(t->t[0]).forEach(System.out::println);

2. 生成
Stream.generate(Math::random).limit(5).forEach(System.out::println);

IntStream ones = IntStream.gengeate(()->1);
IntStream twos = IntStream.gengeate(new IntSupplier(){public int getAsInt(){return 2;}});

//实例
IntSupplier:
IntSupplier fib=new IntSupplier(){
	private int previous=0;
	private int current=1;
	private int getAsInt{
		int oldPrevious=this.previous;
		int nextValue=this.previous.this.current;
		this.previous=nextValue;
		return oldPrevious;
	}
}
IntStream.gengerate(fib).limit(10).forEach(System.out::println);



-------------------------------------------------------------CP6 用流收集数据
//6.1 
//实例:用指令风格对交易按照货币分组
Map<Currency,List<Transaction>> transactionByCurrencies=new HashMap<>();
for(Transaction transaction:transactions){
	Currency currency=transaction.getCurrency();
	List<Transaction> transactionsForCurrency=transactionByCurrencies.get(currency);
	if (transactionsForCurrency==null){
		transactionsForCurrency=new ArrayList<>();
		transactionByCurrencies.put(currency,transactionsForCurrency);
	}
	transactionsForCurrency.add(transaction);
}

===>
Map<Currency,List<Transaction>> transactionByCurrencies=transactions.stream().collect(groupingBy(Transaction::getCurrency));

//6.1 收集器简介 p112
//6.1.1收集器用作高级归约 
List<Transaction> transactions=transactionStream.collect(Collectors.toList());

//6.1.2预定义收集器
functions 
1.将流元素规约和汇总一个值
2.元素分组
3.元素分区

//6.2 归约和汇总
import static java.util.stream.Collectors.*;
long howManyDishes=menu.stream().collect(Collectors.counting());
===>
long howManyDishes=menu.stream().count();

//6.2.1 查找流中最大值和最小值 maxBy & minBy
Comparator<Dish> dishCaloriesComparator=Comparator.comparingInt(Dish::getCalories);
Optional<Dish> mostCalorieDish=menu.stream().collect(maxBy(dishCaloriesComparator));

//6.2.2 汇总 summing & summarizing
//Collectors类:Collectors.summingInt
int totalCalories=menu.stream().collect(summingInt(Dish::getCalories)); //计算菜单列表总热量
//Collectors类:Collectors.averagingInt (averagingLong/averagingDouble)
double avgCalories=menu.stream().collect(averagingInt(Dish::getCalories));
//Collectors类:Collectors.summarizing
IntSummaryStatistics menuStatistics=menu.stream().collect(summarizingInt(Dish::getCalories));

//6.2.3连接字符串 joining
String shortMenu=menu.stream().map(Dish::getName).collect(joining(", "));

//6.2.4 广义的归约汇总 Collectors.reducing
int totalCalories=menu.stream().collect(reducing(0,Dish::getCalories,(i,j)->i+j));
reducing(a,b,c)
--a:   归约初始参数
--b:   映射函数(int)
--c:   BinaryOperator, lambda
Optional<Dish> mostCalorieDish=menu.stream().collect(reducing(d1,d2)->d1.getCalories()>d2.getCalories() ? d1:d2)

//收集与归约
Stream<Integer> stream = Arrays.asList(1,2,3,4,5,6).stream();
List<Integer> numbers=stream.reduce(new ArrayList<Integer>(),
                (List<Integer> l, Integer e)->{l.add(e);return l;},
                (List<Integer> l1, List<Integer> l2)->{l1.addAll(l2);return l1;});


//6.2.4.1 收集框架的灵活性:以不同的方法执行同样的操作
int totalCalories=menu.stream().collect(reducing(0,Dish::getCalories,Integer::sum)); //计算卡路基总和
~~~>
public static <T> Collector<T,?,Long> counting(){return reducing(0L,e->1L,Long::sum);}
~~~>
int totalCalories=menu.stream().map(Dish::getCalories).reduce(Integer::sum).get();
~~~>
int totalCalories=menu.stream().mapToInt(Dish::getCalories).sum();

//6.2.4.2 根据情况选择最佳解决方案 P120
//实例:用reducing连接字符串
String shortMenu=menu.stream().map(Dish::getName).collect(joining());

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//实例:Dish
import java.util.*;
import static java.util.Arrays.asList;
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) {
        this.name = name;
        this.vegetarian = vegetarian;
        this.calories = calories;
        this.type = type;
    }

    public String getName() {return name;}
    public boolean isVegetarian() {return vegetarian;}
    public int getCalories() {return calories;}
    public Type getType() {return type;}
    public enum Type { MEAT, FISH, OTHER }
    @Override
    public String toString() {return name;}
    public static final List<Dish> menu =
            asList( new Dish("pork", false, 800, Dish.Type.MEAT),
                    new Dish("beef", false, 700, Dish.Type.MEAT),
                    new Dish("chicken", false, 400, Dish.Type.MEAT),
                    new Dish("french fries", true, 530, Dish.Type.OTHER),
                    new Dish("rice", true, 350, Dish.Type.OTHER),
                    new Dish("season fruit", true, 120, Dish.Type.OTHER),
                    new Dish("pizza", true, 550, Dish.Type.OTHER),
                    new Dish("prawns", false, 400, Dish.Type.FISH),
                    new Dish("salmon", false, 450, Dish.Type.FISH));
    public static final Map<String, List<String>> dishTags = new HashMap<>();
    static {
        dishTags.put("pork", asList("greasy", "salty"));
        dishTags.put("beef", asList("salty", "roasted"));
        dishTags.put("chicken", asList("fried", "crisp"));
        dishTags.put("french fries", asList("greasy", "fried"));
        dishTags.put("rice", asList("light", "natural"));
        dishTags.put("season fruit", asList("fresh", "natural"));
        dishTags.put("pizza", asList("tasty", "salty"));
        dishTags.put("prawns", asList("tasty", "roasted"));
        dishTags.put("salmon", asList("delicious", "fresh"));
    }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//6.3 分组 groupingBy
import java.util.*;
import static java.util.stream.Collectors.*;
import static lambdasinaction.chap6.Dish.dishTags;
import static lambdasinaction.chap6.Dish.menu;

public class Grouping {
    enum CaloricLevel { DIET, NORMAL, FAT };
    public static void main(String ... args) {
        System.out.println("Dishes grouped by type: " + groupDishesByType());
        System.out.println("Dish names grouped by type: " + groupDishNamesByType());
        System.out.println("Dish tags grouped by type: " + groupDishTagsByType());
        System.out.println("Caloric dishes grouped by type: " + groupCaloricDishesByType());
        System.out.println("Dishes grouped by caloric level: " + groupDishesByCaloricLevel());
        System.out.println("Dishes grouped by type and caloric level: " + groupDishedByTypeAndCaloricLevel());
        System.out.println("Count dishes in groups: " + countDishesInGroups());
        System.out.println("Most caloric dishes by type: " + mostCaloricDishesByType());
        System.out.println("Most caloric dishes by type: " + mostCaloricDishesByTypeWithoutOprionals());
        System.out.println("Sum calories by type: " + sumCaloriesByType());
        System.out.println("Caloric levels by type: " + caloricLevelsByType());
    }

    private static Map<Dish.Type, List<Dish>> groupDishesByType() {return menu.stream().collect(groupingBy(Dish::getType));} //根据dish.type分组
    private static Map<Dish.Type, List<String>> groupDishNamesByType() {return menu.stream().collect(groupingBy(Dish::getType, mapping(Dish::getName, toList())));}
    private static Map<Dish.Type, Set<String>> groupDishTagsByType() {return menu.stream().collect(groupingBy(Dish::getType, flatMapping(dish -> dishTags.get( dish.getName() ).stream(), toSet())));
}

    private static Map<Dish.Type, List<Dish>> groupCaloricDishesByType() {
//        return menu.stream().filter(dish -> dish.getCalories() > 500).collect(groupingBy(Dish::getType));
        return menu.stream().collect(groupingBy(Dish::getType, filtering(dish -> dish.getCalories() > 500, toList())));
    }
//根据卡路里等级对dish进行分组
    private static Map<CaloricLevel, List<Dish>> groupDishesByCaloricLevel() {
        return menu.stream().collect(
                groupingBy(dish -> {
                    if (dish.getCalories() <= 400) return CaloricLevel.DIET;
                    else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
                    else return CaloricLevel.FAT;
                } ));
    }
//6.3.1多级分组:根据dish.type和卡路里等级对dish进行分组
    private static Map<Dish.Type, Map<CaloricLevel, List<Dish>>> groupDishedByTypeAndCaloricLevel() {
        return menu.stream().collect(
                groupingBy(Dish::getType,
                        groupingBy((Dish dish) -> {
                            if (dish.getCalories() <= 400) return CaloricLevel.DIET;
                            else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
                            else return CaloricLevel.FAT;
                        } )
                )
        );
    }
//6.3.2 按子组收集数据
    private static Map<Dish.Type, Long> countDishesInGroups() {return menu.stream().collect(groupingBy(Dish::getType, counting()));} //计算各个type下菜品数量
//根据dish.type分组然后计算各组下最高热量的菜
    private static Map<Dish.Type, Optional<Dish>> mostCaloricDishesByType() {
        return menu.stream().collect(
                groupingBy(Dish::getType,reducing((Dish d1, Dish d2) -> d1.getCalories() > d2.getCalories() ? d1 : d2))
		);
    }
//6.3.2.1 把收集器的结果转换为另一种类型
    private static Map<Dish.Type, Dish> mostCaloricDishesByTypeWithoutOprionals() {
        return menu.stream().collect(
                groupingBy(Dish::getType,
                        collectingAndThen(
                                reducing((d1, d2) -> d1.getCalories() > d2.getCalories() ? d1 : d2),
                                Optional::get)));
    }

    private static Map<Dish.Type, Integer> sumCaloriesByType() {
        return menu.stream().collect(groupingBy(Dish::getType,summingInt(Dish::getCalories)));
    }

    private static Map<Dish.Type, Set<CaloricLevel>> caloricLevelsByType() {
        return menu.stream().collect(
                groupingBy(Dish::getType, mapping(
                        dish -> { if (dish.getCalories() <= 400) return CaloricLevel.DIET;
                        else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
                        else return CaloricLevel.FAT; },
                        toSet() )));
    }
}

//6.4 分区 partitionBy
import java.util.*;
import static java.util.Comparator.comparingInt;
import static java.util.stream.Collectors.*;
import static lambdasinaction.chap6.Dish.menu;

public class Partitioning {
    public static void main(String ... args) {
        System.out.println("Dishes partitioned by vegetarian: " + partitionByVegeterian());
        System.out.println("Vegetarian Dishes by type: " + vegetarianDishesByType());
        System.out.println("Most caloric dishes by vegetarian: " + mostCaloricPartitionedByVegetarian());
    }

    private static Map<Boolean, List<Dish>> partitionByVegeterian() {
        return menu.stream().collect(partitioningBy(Dish::isVegetarian));
    }

    private static Map<Boolean, Map<Dish.Type, List<Dish>>> vegetarianDishesByType() {
        return menu.stream().collect(partitioningBy(Dish::isVegetarian, groupingBy(Dish::getType)));
    }

    private static Object mostCaloricPartitionedByVegetarian() {
        return menu.stream().collect(
                partitioningBy(Dish::isVegetarian,
                        collectingAndThen(
                                maxBy(comparingInt(Dish::getCalories)),
                                Optional::get)));
    }
}


//6.4.1 分区的优势
//实例:根据是否是素食分类再按dish.type分组
Map<Boolean,Map<Dish.Type,List<Dish>>> vegetarianDishesByType=menu.stream().collect(partitioningBy(Dish::isVegetarian,groupingBy(Dish::getType)));
//实例:查找素食与非素食中热量最高的菜
Map<Boolean,Dish> mostCaloricPartitionByVegetarian=menu.stream().collect(partitioningBy(Dish::isVegetarian,collectioningAndThen(maxBy(comparingInt(Dish::getCalories)),optional::get)));


//6.4.2 将数字按质数和非质数分区
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
import static java.util.stream.Collectors.*;
import static java.util.stream.Collector.Characteristics.*;

public class PartitionPrimeNumbers {
    public static void main(String ... args) {
        System.out.println("Numbers partitioned in prime and non-prime: " + partitionPrimes(100));
        System.out.println("Numbers partitioned in prime and non-prime: " + partitionPrimesWithCustomCollector(100));

    }
//将前n个自然数按质数和非质数分区
    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((double) candidate)) - 1) //限制除数不超过被测试数的平方根
                .noneMatch(i -> candidate % i == 0);
    }

    public static Map<Boolean, List<Integer>> partitionPrimesWithCustomCollector(int n) {
        return IntStream.rangeClosed(2, n).boxed().collect(new PrimeNumbersCollector());
    }

    public static boolean isPrime(List<Integer> primes, Integer candidate) {
        double candidateRoot = Math.sqrt((double) candidate);
        //return takeWhile(primes, i -> i <= candidateRoot).stream().noneMatch(i -> candidate % i == 0);
        return primes.stream().takeWhile(i -> i <= candidateRoot).noneMatch(i -> candidate % i == 0);
    }
/*
//takeWhile 方法
    public static <A> List<A> takeWhile(List<A> list, Predicate<A> p) {
        int i = 0;
        for (A item : list) {
            if (!p.test(item)) {return list.subList(0, i);}
            i++;
        }
        return list;
    }
*/
    public static class PrimeNumbersCollector 
	implements Collector<Integer, Map<Boolean, List<Integer>>, Map<Boolean, List<Integer>>> {

        @Override
        public Supplier<Map<Boolean, List<Integer>>> supplier() {
            return () -> new HashMap<Boolean, List<Integer>>() {{
                put(true, new ArrayList<Integer>());
                put(false, new ArrayList<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;
            };
        }

        @Override
        public Function<Map<Boolean, List<Integer>>, Map<Boolean, List<Integer>>> finisher() {
            return i -> i;
        }

        @Override
        public Set<Characteristics> characteristics() {
            return Collections.unmodifiableSet(EnumSet.of(IDENTITY_FINISH));
        }
    }

    public Map<Boolean, List<Integer>> partitionPrimesWithInlineCollector(int n) {
        return Stream.iterate(2, i -> i + 1).limit(n)
                .collect(
                        () -> new HashMap<Boolean, List<Integer>>() {{
                            put(true, new ArrayList<Integer>());
                            put(false, new ArrayList<Integer>());
                        }},
                        (acc, candidate) -> {
                            acc.get( isPrime(acc.get(true), candidate) )
                                    .add(candidate);
                        },
                        (map1, map2) -> {
                            map1.get(true).addAll(map2.get(true));
                            map1.get(false).addAll(map2.get(false));
                        });
    }
}

##Collectors类的静态工厂方法
工厂方法 				返回类型 				用于
toList 					List 					把流中所有项目收集到一个List
示例:List<Dish> dishes=menuStream.collect(toList());
toSet 					Set 					把流中所有项目收集到一个Set,删除重复项
示例:Set<Dish> dishes=menuStream.collect(toSet());
toCollection 			Collection 				把流中所有项目收集到给定的供应源创建的集合
示例:Collection<Dish> dishes=menuStream.collect(toCollection(),ArrayList::new);
counting		 		Long 					计算流中元素的个数
示例:long howManyDishes=menuStream.collect(counting());
summingInt 				Integer 				对流中项目的一个整数属性求和
示例:int totalCalories=menuStream.collect(summingInt(Dish::getCalories));
averagingInt 			Double 					计算流中项目Integer 属性的平均值
示例:double avgCalories=menuStream.collect(averagingInt(Dish::getCalories));
summarizingInt		 	IntSummaryStatistics 	收集关于流中项目Integer 属性的统计值,例如最大、最小、总和与平均值
示例:IntSummaryStatistics menuStatics=menuStream.collect(maxBy(comparingInt(Dish::getCalories)));
joining` 				String 					连接对流中每个项目调用toString 方法所生成的字符串
示例:String shortMenu=menuStream.map(Dish::getName).collect(joining(", "));
maxBy 					Optional 				一个包裹了流中按照给定比较器选出的最大元素的Optional,或如果流为空则为Optional.empty()
示例:Optional<Dish> fattest=menuStream.collect(maxBy(comparingInt(Dish::getCalories)));
minBy 					Optional 				一个包裹了流中按照给定比较器选出的最小元素的Optional,或如果流为空则为Optional.empty()
示例:Optional<Dish> lightest=menuStream.collect(minBy(comparingInt(Dish::getCalories)));
reducing 				归约操作产生的类型 		从一个作为累加器的初始值开始,利用BinaryOperator 与流中的元素逐个结合,从而将流归约为单个值
示例:int totalCalories=menuStream.collect(reducing(0,Dish::getCalories,Integer::sum));
collectingAndThen 		转换函数返回的类型 		包裹另一个收集器,对其结果应用转换函数
示例:int howManyDishes=menuStream.collect(collectingAndThen(toList(),List::size));
groupingBy 				Map K, List 			根据项目的一个属性的值对流中的项目作问组,并将属性值作为结果Map 的键
示例:Map<Dish.Type,List<Dish>> dishesByType=menuStream.colect(groupingBy(Dish::getType));
partitioningBy 			Map Boolean,List 		根据对流中每个项目应用谓词的结果来对项进行分区
示例:Map<Boolean,List<Dish>> vegetarianDishes=menuStream.collect(partitioningBy(Dish::isVegetarian));

//6.5 收集器接口
//实例:6-4 Collector接口
public interface Colllector<T,A,R>{
	Supplier<A> supplier();
	BiComsumer<A,T> accumulator();
	Function<A,R> finisher();
	BinaryOperator<A> combiner();
	Set<Characteristics> characteristics();
}
T:		泛型参数
A:		累加器的类型
R:		收集操作所得到的对象类型

//6.5.1理解Collector接口声明的方法 P130
1. 建立新的结果容器:supplier方法
public Supplier<List<T>> supplier(){return () -> new ArrayList<T>();}
~~~>
public Supplier<List<T>> supplier(){return ArrayList::new ;}

2. 将元素添加到结果容器:accumulator 方法
public BiComsumer<List<T>,T> accumulator(){return (list,item)->list.add(item);}
~~~>
public BiComsumer<List<T>,T> accumulator(){return List::add;}

3. 对结果容器应用最终转换:finisher方法
public Function<List<T>,List<T>> finisher(){return Function.identity();}

4. 合并两个结果容器:combiner方法
public BinaryOperator<List<T>> combiner{return (list1,list2)->{list1.addAll(list2);return list1;}}

5. characteristics方法
包含三个项目的枚举
UNORDERED			规约结果不受流中项目的遍历和累积顺序的影响
CONCURRENT			accumulator函数可以从多个线程同时调用,且该收集器可以并行归约流
IDENTITY_FINISH		完成器方法返回的函数是一个恒等函数。

//6.5.2 全部融合在一起
//实例: ToListCollector
import java.util.*;
import java.util.function.*;
import java.util.stream.Collector;
import static java.util.stream.Collector.Characteristics.*;

public class ToListCollector<T> implements Collector<T, List<T>, List<T>> {
    @Override
    public Supplier<List<T>> supplier() {return () -> new ArrayList<T>();}
    @Override
    public BiConsumer<List<T>, T> accumulator() {return (list, item) -> list.add(item);}
    @Override
    public Function<List<T>, List<T>> finisher() {return i -> i;}
    @Override
    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));
	}
}

//进行自定义收集而非实现Collector
List<Dish> dishes=menuStream.collect(
									ArrayList::new,			//	供应源
									List::add,				//累加器
									List::addAll			//组合器
									);

//6.6 开发你自己的收集器以获得更好的性能

//6.6.1 仅用质数做除数
public static boolean isPrime(List<Integer> primes,int candidate){return primes.stream().noneMatch(i->candidate%i==0);}

//takeWhile 方法
public static <A> List<A> takeWhile(List<A> list, Predicate<A> p) {
	int i = 0;
	for (A item : list) {
		if (!p.test(item)) {return list.subList(0, i);}
		i++;
	}
	return list;
}

===>
public static boolean isPrime(List<Integer> primes, Int candidate) {
        int candidateRoot =(int) Math.sqrt((double) candidate);
		return takeWhile(primes, i -> i <= candidateRoot).stream().noneMatch(i -> candidate % i == 0);
}

//开发collector接口
1. 第一步:定义Collector类的签名
public interface Collector<T,A,R>

----------------------------------------------------------------------------------
//6.6.1 仅用质数做除数


//开发Collector接口 p136
step 1: 定义Collector类的签名
public class PrimeNumbersCollector implements Collector<Integer,Map<Boolean,List<Integer>>,Map<Boolean,List<Integer>>>

step 2:实现归约过程
public Supplier<Map<Boolean,List<Integer>>> supplier(){
	return () -> new HashMap<Map<Boolean,List<Integer>>(){{
		put(true,new ArrayList<Integer>());
		put(false,new ArrayList<Integer>());
	}};
}

public BiComsumer<Map<Boolean,List<Integer>>,Integer> accumulator(){
	return (Map<Boolean,List<Integer>> acc,Integer candidate) -> {
		acc.get(isPrime(acc.get(true),candidate)).add(candidate);
	};
}

step 3: 让收集器并行工作
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;
	};
}

step 4: finisher方法和收集器的characteristics方法
public Function<Map<Boolean,List<Integer>>,Map<Boolean,List<Integer>>> finisher(){return Function.identity();}


//运用自写的收集器重写代码
import java.util.*;
import java.util.function.*;
import java.util.stream.Collector;

public class PrimeNumbersCollector implements Collector<Integer,Map<Boolean,List<Integer>>,Map<Boolean,List<Integer>>>{
    //创建结果容器
    public Supplier<Map<Boolean,List<Integer>>> supplier() {
        return () -> new HashMap<Boolean,List<Integer>>(){{
            put(true,new ArrayList<>());
            put(false,new ArrayList<>());
        }};
    }

    // 作用:将元素添加到结果容器
    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);
        };
    }

    //对结果容器进行转换
    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;
			};
    }

    // 作用:当为并行流时,合并两个或多个结果容器
    public Function<Map<Boolean,List<Integer>>,Map<Boolean,List<Integer>>> finisher() {return Function.identity();}

    // 作用:返回一个不可变的 Characteristics 集合
    public Set<Characteristics> characteristics() {return Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));}

    //行为参数化方法
    public static <A> List<A> takeWhile(List<A> list, Predicate<A> p){
        int  i = 0;
        for(A item : list){
            if(!p.test(item)){return list.subList(0,i);}
            i++;
        }
        return list;
    }

    // 主要判断逻辑()判断是否是质数
    public static boolean isPrime(List<Integer> primes,int candidate){
	int candidateRoot = (int)Math.sqrt((double)candidate);
	return takeWhile(primes,i -> i <= candidateRoot).stream().noneMatch(p ->candidate % p == 0);
	}
    }


//6.6.2 比较收集器性能
import java.util.function.*;
public class CollectorHarness {
	public static void main(String[] args) {
	//System.out.println("Partitioning done in: " + execute(PartitionPrimeNumbers::partitionPrimes) + " msecs");
	System.out.println("Partitioning done in: " + execute(PartitionPrimeNumbers::partitionPrimesWithCustomCollector) + " msecs" );
       }

    private static long execute(Consumer<Integer> primePartitioner) {
	long fastest = Long.MAX_VALUE;
	for (int i = 0; i < 10; i++) {
		long start = System.nanoTime();
		primePartitioner.accept(1_000_000);
		long duration = (System.nanoTime() - start) / 1_000_000;
		if (duration < fastest) {fastest = duration;}
		System.out.println("done in " + duration);
        }
        return fastest;
    }
}


===>_finally
public Map<Boolean,List<Integer>> partitionPrimesWithCustomCollector(int n){
		IntStream.rangeClosed(2,n).boxed()
			.collect(
				()->new HashMap<Boolean,List<Integer>>(){{
					put(true,new ArrayList<Integer>());
					put(false,new ArrayList<Integer>());
				}},
				(acc,candidate)->{acc.get(isPrime(acc.get(true),candidate)).add(candidate);},

				(map1,map2)->{map1.get(true).addAll(map2.get(true));
						map.get(false).addAll(map2.get(false));
				});
}


----------------------------------------------------------------------------------cp7 并行数据处理与性能
//7.1 并行流 parallelStream
//实例:前n项累计求和
public static long sequentialSum(long n){
	return Stream.iterate(1L,i->i+1).limit(n).reduce(0L,Long::sum);
}
//传统写法
public static long iterativeSum(long n){
	long result = 0;
	for (long i=1L;i<=n;i++){result+=i;}
	return result;
} 
##python
def cum(a,b):
   sum=0
   for i in range(a,b+1):sum+=i
   return sum


//7.1.1 将顺序流转换为并行流
public static long parallelSum(long n){
	return Stream.iterate(1L,i->i+1)
					.limit(n)
					.parallel()
					.reduce(0L,Long::sum);
}

//Test
public class Test {
	public static long parallelSum(long n) {
		return Stream.iterate(1L, i -> i + 1).limit(n).parallel().reduce(0L, Long::sum);}
	public static void main(String[] args) {System.out.println(parallelSum(10000));}
}


stream.parallel().filter().sequential().map().parallel().reduce();


//7.1.2 测量流性能
public long measureSumPerf(Function<Long,Long> adder,long n){
	long fastest=Long.MAX_VALUE;
	for(int i=0;i<10;i++){
		long start=System.nanoTime();
		long sum=adder.apply(n);
		long duration=(System.nanoTime()-start)/1_000_000;
		System.out.println("result: "+sum);
		if(duration<fastest) fastest=duration;
	}
	return fastest;
}

System.out.println("parallel sum done in: "+measureSumPerf(ParallelStream::parallelSum,10_000_000)+" msecs ")

//使用 LongStream.rangeClosed方法 进行分块计算
public static long rangedSum(long n){return LongStream.rangeClosed(1,n).reduce(0L,Long::sum);}
System.out.println("Parallel range sum done in:"+measureSumPerf(ParallelStreams::parallelRangedSum,10_000_000)+"msecs");


//7.1.3 正确使用并行流
//累和
public static long sideEffectSum(long n){
	Accumulator accumulator = new Accumulator();
	LongStream.rangeClosed(1,n).forEach(accumulator::add);
	return accumulator.total;
}
public static class Accumulator{
	public long total=0;
	public void add(long value){total+=value;}
}

//并行累和
public static long sideEffectParallelSum(long n){
	Accumulator accumulator=new Accumulator();
	LongStream.rangeClosed(1,n).parallel().forEach(accumulator::add);
	return accumulator.total;
}
System.out.println("SideEffect parallel sum done in: " + measurePerf(ParallelStreams::sideEffectParallelSum,10_000_000L)+" msecs")


//7.1.4 高效使用并行流
流的数据源和可分解性
ArrayList			very_good
LinkedList			bad
IntStream.range			very_good
Stream.iterate			bad
HashSet				good
TreeSet				good

//7.2 分支/合并 框架
认的线程数量是处理器的数量,可以通过ForkJoinPool.common.parallelism改变线程池大小。

过去的分支合并框架操作的对象是RecursiveTask任务,内容是将一个任务按照一定规则(规则在RecursiveTask内的方法自定义实现)分成多个任务,每个任务继续分,分到不能再分为止,这些任务差不多被平均分配到ForkJoinPoll的所有线程上,每个线程都为分配给他的任务保存一个双向链式队列,每完成一个任务,就用队列头上取出下一个任务开始执行,若某一线程空了,会通过工作窃取(work stealing)“偷”走任务去执行,提高效率。java8里有新的自动机制去拆分流,就是下面要说的 Spliterator。

//7.2.1 使用RecursiveTask
compute:
protected abstract R compute();


//实例:用分支合并框架执行并行求和
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;
import java.util.concurrent.*;
import java.util.function.*;

class ParallelStreamsHarness {
    public static final ForkJoinPool FORK_JOIN_POOL = new ForkJoinPool();
    public static void main(String[] args) {
        System.out.println("Iterative Sum done in: " + measurePerf(ParallelStreams::iterativeSum, 10_000_000L) + " msecs");
        System.out.println("Sequential Sum done in: " + measurePerf(ParallelStreams::sequentialSum, 10_000_000L) + " msecs");
        System.out.println("Parallel forkJoinSum done in: " + measurePerf(ParallelStreams::parallelSum, 10_000_000L) + " msecs" );
        System.out.println("Range forkJoinSum done in: " + measurePerf(ParallelStreams::rangedSum, 10_000_000L) + " msecs");
        System.out.println("Parallel range forkJoinSum done in: " + measurePerf(ParallelStreams::parallelRangedSum, 10_000_000L) + " msecs" );
        System.out.println("ForkJoin sum done in: " + measurePerf(ForkJoinSumCalculator::forkJoinSum, 10_000_000L) + " msecs" );
        System.out.println("SideEffect sum done in: " + measurePerf(ParallelStreams::sideEffectSum, 10_000_000L) + " msecs" );
        System.out.println("SideEffect prallel sum done in: " + measurePerf(ParallelStreams::sideEffectParallelSum, 10_000_000L) + " msecs" );
    }

    public static <T, R> long measurePerf(Function<T, R> f, T input) {
        long fastest = Long.MAX_VALUE;
        for (int i = 0; i < 10; i++) {
            long start = System.nanoTime();
            R result = f.apply(input);
            long duration = (System.nanoTime() - start) / 1_000_000;
            System.out.println("Result: " + result);
            if (duration < fastest) fastest = duration;
        }
        return fastest;
    }
}

---
public class ForkJoinSumCalculator extends java.util.concurrent.RecursiveTask<Long> {
    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;
    }

    @Override
    protected Long compute() {
        int length = end - start;
        if (length <= THRESHOLD) {return computeSequentially();}
        ForkJoinSumCalculator leftTask = new ForkJoinSumCalculator(numbers, start, start + length/2);
        leftTask.fork();
        ForkJoinSumCalculator rightTask = new ForkJoinSumCalculator(numbers, start + length/2, end);
        Long rightResult = rightTask.compute();
        Long leftResult = leftTask.join();
        return leftResult + rightResult;
    }

    private long computeSequentially() {
        long sum = 0;
        for (int i = start; i < end; i++) {sum += numbers[i];}
        return sum;
    }

    public static long forkJoinSum(long n) {
        long[] numbers = LongStream.rangeClosed(1, n).toArray();
        ForkJoinTask<Long> task = new ForkJoinSumCalculator(numbers);
        return FORK_JOIN_POOL.invoke(task);
    }
}
//7.2.3 工作窃取
//7.3 Spliterator 可分迭代器、分布式迭代器
//Spliterator接口
public interface Spliterator<T>{
	boolean tryAdvance(consumer< ? supper T> action);
	Spliterator<T> trySplit();
	long estimateSize();
	int characteristics();
}

//7.3.1 拆分过程
//表 7-2 Spliterator的特征
特征							含义
ORDERED							元素有既定的顺序,因此Spliterator在遍历和划分时也会遵循这一顺序
DEITINCT						对于任意一对遍历过得元素x和y,x.equals(y)返回false
SORTED							遍历的元素按照一个预定义的顺序排序
SIZED							该Spliterator由一个已知大小的源建立,因此estimatedSize()返回的是准确值
NONNULL							保证遍历的元素不会为null
IMMUTABLE						Spliterator的数据源不能修改。这意味着在遍历时不能添加,删除或修改任何元素
CONCURRENT						该Spliterator的数据源可以被其他线程同事修改而无需同步
SUBSIZED						该Spliterator和所有从它拆分出来的Spliterator都是SIZED

//7.3.2 实现你自己的Spliterator
public class tes{
	public static int countWordsIteratively(String s){
		int counter = 0;
		boolean lastSpace = true;
		for(char c:s.toCharArray()){
			if(Character.isWhitespace(c)){lastSpace=true;}
			else{if (lastSpace) counter++;lastSpace=false;}
		}
		return counter;
	}
	public static void main(String[] args){
		final String SENTENCE="im zieox , this name is not only specal "+"also fantastic"+" woo,hahahhaha!";
		System.out.println("Found "+countWordsIteratively(SENTENCE)+" words");
	}
}

---<output>
Found 12 words

//7.3.2.1以函数式风格重写单词计数器
Stream<Character> stream=IntStream.range(0,SENTENCE.length()).mapToObj(SENTENCE::charAt);


//实例:WordCount
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
public class WordCount {
	public static final String SENTENCE =
	" Nel   mezzo del cammin  di nostra  vita " +"mi  ritrovai in una  selva oscura"
	+" che la  dritta via era   smarrita ";
	public static void main(String[] args) {
		System.out.println("Found " + countWordsIteratively(SENTENCE) + " words");
		System.out.println("Found " + countWords(SENTENCE) + " words");
	}
	
	public static int countWordsIteratively(String s) {
		int counter = 0;
		boolean lastSpace = true;
		for (char c : s.toCharArray()) {
			if (Character.isWhitespace(c)) {lastSpace = true;}
			else {
				if (lastSpace) counter++;
				lastSpace = Character.isWhitespace(c);
				}
			}
		return counter;
	}
	
	public static int countWords(String s) {
		//Stream<Character> stream = IntStream.range(0, s.length()).mapToObj(SENTENCE::charAt).parallel();
		Spliterator<Character> spliterator = new WordCounterSpliterator(s);
		Stream<Character> stream = StreamSupport.stream(spliterator, true);
		return countWords(stream);
	}
	
	private static int countWords(Stream<Character> stream) {
		WordCounter wordCounter = stream.reduce(new WordCounter(0, true),
                                                WordCounter::accumulate,
                                                WordCounter::combine);
							return wordCounter.getCounter();
    }

    private static class WordCounter {
        private final int counter;
        private final boolean lastSpace;

        public WordCounter(int counter, boolean lastSpace) {
            this.counter = counter;
            this.lastSpace = lastSpace;
        }

        public WordCounter accumulate(Character c) {
            if (Character.isWhitespace(c)) {return lastSpace ? this : new WordCounter(counter, true);}
			else {return lastSpace ? new WordCounter(counter+1, false) : this;}
		}

        public WordCounter combine(WordCounter wordCounter) {
			return new WordCounter(counter + wordCounter.counter, wordCounter.lastSpace);
		}
		
		public int getCounter() {return counter;}
	}

    private static class WordCounterSpliterator implements Spliterator<Character> {
        private final String string;
        private int currentChar = 0;
        private WordCounterSpliterator(String string) {this.string = string;}
        @Override
        public boolean tryAdvance(Consumer<? super Character> action) {
			action.accept(string.charAt(currentChar++));
			return currentChar < string.length();
		}
		
		@Override
        public Spliterator<Character> trySplit() {
			int currentSize = string.length() - currentChar;
			if (currentSize < 10) {return null;}
			for (int splitPos = currentSize / 2 + currentChar; splitPos < string.length(); splitPos++) {
				if (Character.isWhitespace(string.charAt(splitPos))) {
					Spliterator<Character> spliterator = new WordCounterSpliterator(string.substring(currentChar, splitPos));
					currentChar = splitPos;
					return spliterator;
				}
			}
			return null;
		}
		
        @Override
        public long estimateSize() {return string.length() - currentChar;}
        @Override
        public int characteristics() {return ORDERED + SIZED + SUBSIZED + NONNULL + IMMUTABLE;}
	}
}

//运用WordCounterSpliterator
Spliterator<Character> spliterator=new WordCounterSpliterator(SENTENCE);
Stream<Character> stream=StreamSupport.stream(spliterator,true);
System.out.println("Found "+countWords(stream)+" words")


----------------------------------------------------------------------------------cp8 重构,测试和调试
//8.1为改善可读性和灵活性重构代码
//8.1.1改善代码可读性
//8.1.2从匿名类到Lambda表达式的转换

//实现单一抽象方法的匿名类转换为Lambda
Runnable r1 = new Runnable(){public void run(){System.out.println("hello");}};
===>转换为lambda表达式
Runnable r2 = () -> System.out.println("hello");

-------------error------------------
int a =10;
Runnable r1 = () -> { 
	int a=2;
	System.out.println(a);
	};
-------------error------------------

Runnable r2 = new Runnable(){
	public void run(){
		int a = 2;
		System.out.println(a);
	}
};

---P166
interface Task{public void execute();}
public static void doSomething(Runnable r){r.run();}
public static void doSomething(Task a){a.execute();}

doSomething(new Task(){public void execute(){System.out.println("Danger danger!!");}});
doSomething(()->System.out.println("Danger danger!!"));
doSomething((Task)()->System.out.println("Danger danger!!"));


//8.1.3 从lambda表达式到方法引用的转换
//实例:对菜单热量进行分类
Map<CaloricLevel,List<Dish>> dishesByCaloricLevel=menu.stream().collect(
	groupingBy(dish->{
			if(dish.getCalories()<=400) return CaloricLevel.DIET;
			else if (dish.getCalories()<=700) return CaloricLevel.NORMAL;
			else return CaloricLevel.FAT;
			}));

===>
Map<CaloricLevel,List<Dish>> dishesByCaloricLevel=menu.stream().collect(groupingBy(Dish::getCaloricLevel));
public class Dish{
...
	public CaloricLevel getCaloricLevel(){
		if(this.getCalories()<=400)return CaloricLevel.DIET;
		else if (dish.getCalories()<=700) return CaloricLevel.NORMAL;
		else return CaloricLevel.FAT;
	}
}

//实例:优化 (重量排序)
inventory.sort((Apple a1,Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));
inventory.sort(comparing(Apple::getWeight));
//计算热量总和
int totalCalories=menu.stream().map(Dish::getCalories).reduce(0,(c1,c2)->c1+c2);
===>use summingInt
int totalCalories=menu.stream().collect(summingInt(Dish::getCalories));

//8.1.4 从命令式的数据处理切换到Stream

List<String> dishName=new ArrayList<>();
for(Dish dish:menu){if(dish.getCalories()>300){dishName.add(dish.getName());}}
===>使用stream优化
menu.parallelStream().filter(d->d.getCalories()>300).map(Dish::getName).collect(toList());


//8.1.5 增加代码灵活性 p168
1. 采用函数接口
2. 有条件的延迟执行
3. 环绕执行
String oneLine = processFile((BufferedReader b)->b.readLine());
String twoLine = processFile((BufferedReader b)->b.readLine()+b.readLine());
public static String processFile(BufferedReaderProcessor p) throws IOException{
	try(BufferedReader br=new BufferedReader(new FileReader("java8inaction/vhap8/data.txt"))){return p.process(br);}
}
public interface BufferedReaderProcessor{String process(BufferedReader b) throws IOException;}


//8.2 使用Lambda重构面向对象的设计模式
https://www.jianshu.com/p/26551349573f
//8.2.1策略模式

//定义一个验证文本接口
public interface ValidationStrategy{boolean execute(String s);}
//定义该接口的一个或多个具体实现
public class IsAllLowerCase implements ValidationStrategy{public boolean execyte(String s){return s.matches("[a-z]+");}}
public class IsNumeric implements ValidationStrategy{public boolean execute(String s){return  s.matches("\\d+");}}
--->
public class Validator{
	private final ValidationStrategy strategy;
	public Validator(ValidationStrategy v){this.strategy=v;}
	public boolean validate(String s){return strategy.execute(s);}
}

Validator numericValidator=new Validator(new IsNumeric());
boolean b1=numericValidator.validate("aaa");
Validator lowerCaseValidator=new Validator(new IsAllLowerCase());
boolean b2=lowerCaseValidator.validate("bbb");

//使用lambda表达式
Validator numericValidator=new Validator((String s)->s.matches("[a-z]+"));
boolean b1=numericValidator.validate("aaa");
Validator lowerCaseValidator=new Validator((String s)->s.matches("\\d+"));
boolean b2=lowerCaseValidator.validate("bbb");

//8.2.2模板方法
//实例:onlinebank
abstract class OnlineBank{
	public void processCustomer(int id){
			Customer c=Database.getCustomerWithId(id);
			makeCustomerHappy(c);
	}
	abstract void makeCustomerHappy(Customer c);

}
//use:lambda
public void processCustomer(int id,Customer<Customer> makeCustomerHappy){
	Customer c=Database.getCustomerWithId(id);
	makeCustomerHappy.accept(c);
}
//use the_lambding inserting
new OnlineBankingLambda().processCustomer(1377,(Customer c)->System.out.println("Hello "+c.getName());

//8.2.3 观察者模式
//创建观察者接口
interface Observer{void notify(String tweet);}
//
class NYTimes implements Observer{
	public void notify(String tweet){
		if(tweet != null && tweet.comtains("money")){System.out.println("Yet another news: "+tweet);}
	}
}
//
class Guardian implements Observer{
	public void notify(String tweet){
		if(tweet != null && tweet.comtains("queen")){System.out.println("Yet another news: "+tweet);}
	}
}
//
class LeMonde implements Observer{
	public void notify(String tweet){
		if(tweet != null && tweet.comtains("wine")){System.out.println("Yet another news: "+tweet);}
	}
}
//定义subject接口
interface Subject{
	void registerObserver(Observer o);
	void notifyObservers(String tweet);
}

//
class Feed implements Subject{
	private final List<Observer> observers=new ArrayList<>();
	public void registerObserver(Observer o){this.observers.add(o);}
	public void notifyObservers(String tweet){observers.forEach(o->o.notify(tweet));}
}

Feed f=new Feed();
f.registerObserver(new NYTimes());
f.registerObserver(new Guardian());
f.registerObserver(new LeMonde());
f.notifyObservers("The queen said her favourite book is Java 8 in Action!");


//使用Lambda表达式
f.registerObserver((String tweet)->{
	if(tweet != null && tweet.contains("money")){System.out.println("Breaking news in NY! "+tweet);}
		});
---
f.registerObserver((String tweet)->{
	if(tweet != null && tweet.contains("queen")){System.out.println("Yet another news in London..."+tweet);}
		});

//8.2.4 责任链模式
责任链模式是一种创建处理对象序列(比如操作序列)的通用方案。
一个处理对象可能需要在完成一些工作之后,将结果传递给另一个对象,
这个对象接着做一些工作,再转交给下一个处理对象,以此类推。
通常,这种模式是通过定义一个代表处理对象的抽象类来实现的,在抽象类中会定义一个字段来记录后续对象。
一旦对象完成它的工作,处理对象就会将它的工作转交给它的后继。 
代码中,这段逻辑看起来是下面这样:

public abstract class ProcessingObject<T> {
    protected ProcessingObject<T> successor;
    public void setSuccessor(ProcessingObject<T> successor){this.successor = successor;}
    public T handle(T input){
		T r = handleWork(input);
		if(successor != null){return successor.handle(r);}
		return r;
	}
	abstract protected T handleWork(T input);
}

public class HanderTextProcessing extends ProcessingObject<String>{
	public String handleWork(String text){return "From Raoul,Mario and Alen: "+text;}
}

public class SpellCheckerProcessing extends ProcessingObject<String>{
	public String handleWork(String text){return text.replaceAll("labda","lambda");}
}

===>
ProcessingObject<String> p1 = new HanderTextProcessing();
ProcessingObject<String> p2 = new SpellCheckerProcessing();
p1.setSuccessor(p2);
String result=p1.handle("Aren't labdas really sexy?!!");
System.out.println(result);

//使用Lambda表达式
UnaryOperator<String> headerProcessing=(String text)->"From Raoul,Mario and Alen: "+text;
UnaryOperator<String> spellCheckerProcessing=(String text)->text.replaceAll("labda","lambda");
Function<String,String> pipeline=headerProcessing.andThen(spellCheckerProcessing);
String result=pipeline.apply("Aren't labdas really sexy?!!");

//8.2.5 工厂模式
public class ProductFactory{
	public static Product createProduct(String name){
		switch(name){
			case "loan":return new loan();
			case "stock":return new stock();
			case "bond":return new bound();
			default:throw new RuntimeException("No such product "+name);
		}	
	}
}
//使用传统方法创建loan
Product p = ProductFactory.createProduct("loan");
===>use:lambda
Supplier<Product> loanSupplier=loan::new;
Loan loan=loanSupplier.get();
final static Map<String,Supplier<Product>> map=new HashMap<>();
static {
	map.put("loan",loan::new);
	map.put("stock",stock::new);
	map.put("bond",bond::new);
}

public static Product createProduct(String name){
	Supplier<Product> p=map.get(name);
	if(p!=null) return p.get();
	throw new IllegalArgumentException("No such product "+name);
}

//
public interface TriFunction<T,U,V,R>{R apply(T t,U u,V v);}
Map<String,TriFunction<Integer,Integer,String,Product>> map=new HashMap();

//8.3 测试lammbda表达式
public class Point{
	private final int x;
	private final int y;
	private Point(int x,int y){this.x=x;this.y=y;}
	public int getX(){return x;}
	public int getY(){return y;}
	public Point moveRightBy(int x){return new Point(this.x+x,this.y);}
}

public void testmoveRightBy() throw Exception{
	Point p1=new Point(5,5);
	Point p2=p1.moveRightBy(10);
	assertEquals(15,p2.getX());
	assertEquals(5,p2.getY());
}

//8.3.1 测试可见的lambda函数行为 P179

//8.3.2 测试使用Lambda的方法的行为
public static List<Point> moveAllPointsRightBy(List<Point> points,int x){
	return points.stream().map(p->new Point(p.getX()+x,p.getY())).collect(toList());
}

public void testmoveAllPointsRightBy() throw Exception{
	List<Point> points=Arrays.asList(new Point(5,5),new Point(10,5));
	List<Point> expectedPoints=Arrays.asList(new Point1(5,5),new Point(20,5));
	List<Point> newPoints=Point.moveAllPointsRightBy(points,10);
	assertEquals(expectedPoints,newPoints);
}

//8.3.3 将复杂的Lambda表达式分到不同的方法
//8.3.4 高阶函数的测试
public void testFilter() throws Exception{
	List<Integer> numbers=Arrays,asList(1,2,3,4);
	List<Integer> even=filter(numbers,i->i%2==0);
	List<Integer> smallerThanThree=filter(numbers,i->i<3);
	assertEquals(Arrays.asList(2,4),even);
	assertEquals(Arrays.asList(1,2),smallerThanThree);
}

//8.4 调试
//8.4.1 查看栈跟踪P181
//8.4.2 使用日志调试
List<Integer> numbers=Arrays.asList(1,2,3,4);
numbers.stream().map(x->x+17).filter(x->x%2==0).limit(3).forEach(System.out::println);

//use:peek
List<Integer> result = numbers.stream()
					.peek(x->System.out.println("from stream: "+x))
					.map(x->x+17)
					.peek(x->System.out.println("after map: "+x))
					.filter(x->x%2==0)
					.peek(x->System.out.println("after filter: "+x))
					.limit(3)
					.peek(x->System.out.println("after limit: "+x))
					.collect(toList());


----------------------------------------------------------------------------------cp9 默认方法
//让类自动继承接口的一个默认实现
default void sort(Comparator<? super E> c){Collections.sort(this,c);}
//实例:排序
List<Integer> numbers=Arrays.asList(3,1,2,6,7,3);
numbers.sort(Comparator.naturalOrder());

default Stream<E> stream(){return StreamSupport.stream(spliterator(),false);}

//9.1不断演进的API P187

//9.1.1初始版本的API
public interface Resizable extends Drawable{
	public int getWidth();
	public int getHeight();
	public void setWidth(int width);
	public void setHeight(int height);
	public void setAbsoluteSize(int width, int height);
}

public class Game {
	public static void main(String...args){
		List<Resizable> resizableShapes =Arrays.asList(new Square(),new Triangle(), new Ellipse());
		Utils.paint(resizableShapes);
	}
}

public class Utils{
	public static void paint(List<Resizable> l){l.forEach(r -> { r.setAbsoluteSize(42, 42); });
	//TODO: uncomment, read the README for instructions
	//l.forEach(r -> { r.setRelativeSize(2, 2); });
	}	
}

//9.1.2 第二版API
public interface Resizable extends Drawable{
	public int getWidth();
	public int getHeight();
	public void setWidth(int width);
	public void setHeight(int height);
	public void setAbsoluteSize(int width, int height);
	public void setRelativeSize(int widthFactor, int heightFactor);
}

//9.2 概述默认方法
public interface Sized{
	int size();
	default boolean isEmpty(){return sized()==0;}
}

//
default void setRelativeSize(int wFactor,int hFactor){setAbsoluteSize(getWidth()/wFactor,getHeight()/hFactor);}

//实例:removeIf
default boolean removeIf(Predicate<? super E> filter){
	boolean removed = false;
	Iterator<E> each = iterator();
	while (each.hasnext()){
		if(filter.test(each.next())){
			each.remove();
			removed=true;
		}
	}
	return removed;
}


//9.3 默认方法的使用模式
//9.3.1可选方法
interface Iterator<T>{
	boolean hasNext();
	T next();
	deault void remove(){throw new UnsupportedAddressTypeException();}
}

//9.3.2 行为的多继承
public class ArrayList<E> extends AbstractList<E> implements List<E>,RandomAccess,
Cloneable,Serializable,Iterable<E>,Collection<E>{}
//1.类型的多继承
//2.利用正交方法的精简接口
public interface Rotatable{
	void setRotationAngle(int angleInDegrees);
	int getRotationAngle();
	default void rotateBy(int angleInDegrees){setRotationAngle((getRotationAngle()+angleInDegrees)%360);}
}
//
public interface Moveable{
	int getX();
	int getY();
	void setX(int x);
	void setY(int y);
	default void moveHorizontally(int distance){setX(getX()+distance);}
	default void moveVertically(int distance){setY(getY()+distance);}
}
//realizable 实现码
public interface Resizable{
	int getWidth();
	int getHeight();
	void setWidth(int width);
	void setHeight(int height);
	void setAbsoluteSize(int width,int height);
	default void setRelativeSize(int wFactor,int hFactor){setAbsoluteSize(getWidth()/wFactor,getHeight()/hFactor);}
} 

//3.组合接口
public class monster implements Rotatable,Moveable,Resizable{
	monster m=new monster();
	m.rotateBy(180);
	m.moveVertically(10);
}


//9.4 解决冲突的规则
//一个类对接多接口时,其中方法重名的解决方法
interface A{default void hello(){System.out.println("Hello from A");}}
interface B extends A{default void hello(){System.out.println("Hello from B");}}
public class tes implements B,A{public static void main(String...args){new tes().hello();}}
---<output>---
"Hello from B"

//9.4.1 解决问题的三条规则
1. 类中的方法优先级最高。类或父类中声明的方法的优先级高于任何声明为默认方法的优先级。
2. 如果无法依据第一条进行判断,那么子接口的优先级更高:函数签名相同时,
   优先选择拥有最具体实现的默认方法的接口,即如果B继承了A,那么B就比A更加具体。
3. 最后,如果还是无法判断,继承多个接口的类必须通过显示覆盖和调用期望的方法,显示的1选择使用哪一个默认方法实现

根据优先级(方法高于默认)--->子类高于父类--->显示覆盖

//9.4.2 选择提供了最具体实现的默认方法接口
public class D implements A{}
public class C extends D implements B,A{public static void main(String...args){new C().hello();}}
---<output>---
"Hello from B"
D继承了A的默认方法并未覆盖,但实现了A接口,所以D拥有A的默认方法,而B为A的子类优先级更高。

//9.4.3 冲突及如何显示的消除歧义
public interface A {void hello{System.out.println("Hello from A");}}
public interface B {void hello{System.out.println("Hello from B");}}
public class C implements B,A{}
--->Error:
//解决冲突
public class C implements B,A{void hello(){B.super.hello();}} //显示调用接口中的B.hello()方法

//9.4.4 菱形继承问题
public interface A{default void hello(){System.out.println("Hello from A");}}
public interface B extends A{}
public interface C extends A{}
public class D implements B,C{public static void main(String... args){new D().hello();}}
---<output>---
"Hello from A"
//如果
public inteface C extends A{coid hello();}
//则输出C.hello()


----------------------------------------------------------------------------------cp10 用optional取代null
//10.1 如何为缺失值建模
//实例:with no optional
public class Person{
	private Car car;
	public Car getcar(){return car;}
}

public class Car{
	private Insurance insurance;
	public Insurance getInsurance(){return insurance;}
}

public class Insurance{
	private String name;
	public String getName(){return name;}
}

public String getCarInsuranceName(Person person){return person.getCar().getInsurance().getName();}
--->NullPointException

//10.1.1采用防御式检查减少NullPointException
//实例:采用if语句
public String getCarInsuranceName(Person person){
	if(person !=null){
		Car car = person.getCar();
		if(car != null){
			Insurance insurance=car.getInsurance();
			if(insurance != null){return insurance .getName();}
		}
	}

}

//实例:采用多退出语句
public String getCarInsuranceName(Person person){
	if (person==null){return "Unknown";}
	Car car=person.getCar();
	if(car==null){return "Unknown";}
	Insurance insurance = car.getInsurance();
	if(insurance==null){return "Unknown";}
	return insurance.getName();
}

//10.1.2 null带来的种种问题
//10.1.3 其他语言中的null替代


//10.2 Optional类入门
import java.util.*;
public class Person {
	private Optional<Car> car;
	public Optional<Car> getCar() {return car;}
}

public class Car{
	private Optional<Insurance> insurance;
	public Optional<Insurance> getInsurance(){return insurance;}
}

public class Insurance{
	private String name;
	public String getName(){return name;}
}

//10.3 应用Optional的几种模式
//10.3.1 创建Optional对象
1. 声明一个空Optional 
Optional<Car> optCar=Optional.empty();
2. 依据一个非空值创建Optional
Optional<Car> optCar=Optional.of(car);
3. 可接受null的Optional
Optional<Car> optCar=Optional.ofNullable(car);

//10.3.2 使用map从Optional对象中提取和转换值
//检查对象是否为null
String name=null;
if(insurance != null){name=insurance.getName();}
Optional<Insurance> optInsurance=Optional.ofNullable(insurance);
Optional<String> name=optInsurance.map(Insurance::getName);

public String getCarInsuranceName(Person person){return person.getCar().getInsurance().getName();}

//10.3.3 使用flatMap链接Optional对象
Optional<Person> optPerson=Optional.of(person);

---error---
Optional<String> name=optPerson
			.map(Person::getCar)
			.map(Car::getInsurance)
			.map(Insurance::getName);
---error---

public String getCarInsuranceName(Optional<Person> person){
	return person.flatMap(Person::getCar)
			.flatMap(Car::getInsurance)
			.map(Insurance::getName)
			.orElse("Unknown");
}

//10.3.4 默认行为及解引用Optional对象
get()
orElse()
orElseGet()
orElseThrow()
ifPresent()

//10.3.5 两个Optional对象的组合
public Insurance findCheapestInsurance(Person person,Car car){return cheapestCompany;}

public Optional<Insurance> nullSafeFindCheapestInsurance(Optinal<Person> person,Optional<Car> car){
	if(person.isPresent() && car.isPresent()){return Optional.of(findCheapestInsurance(person.get(),car.get()));}
	else {return Optional.empty();}
}

//10.3.6 使用filter剔除特定值
Insurance insurance=...;
if (insurance != null && "zieox".equals(insurance.getName())){System.out.println("ok");}

Optional<Insurance> optInsurance=...;
optInsurance.filter(insurance->"zieox".equals(insurance.getName())).ifPresent(x-> System.out.println("ok");)

//实例
public String getCarInsuranceName(Optional<Person> person,int minAge){
	return person.filter(p->p.getAge()>=minAge)
			.flatMap(Person::getCar)
			.flatMap(Car::getInsurance)
			.map(Insurance::getName)
			.orElse("Unknown");
}


##表10-1 Optional类的方法
empty					返回一个空的Optional实例
filter					if true return 包含该值的Optional对象,否则返回一个空的Optional对象
flatMap					if 值存在,就对该值执行提供的mapping函数调用,返回Optional类型的值,否则返回一个空的Optional对象
get					if 值存在,就将被Optional封装的值返回,否则抛出以恶搞NoSuchElementException异常
ifPresent				if 值存在,就执行使用该值的方法调用,或什么也不做
isPresent				if 值存在,则返回true 否则false
map					if 值存在,就对该值执行提供的mapping函数调用
of					将指定值用Optional封装之后返回,if null throw NullPointerException异常
ofNullable				将指定值用Optional封装之后返回,if null 返回一个空的Optional对象
orElse					如果有值则将其返回,否则返回一个默认值
orElseGet				如果有值则将其返回,否则返回一个由指定Supplier接口生成的值
orElseThrow				如果有值则将其返回,否则返回一个由指定Supplier接口生成的异常


//10.4 使用Optional的实战示例 p216
//10.4.1用Optional封装可能为null的值
Optional<Object> value=Optional.ofNullable(map.get("key"));

//10.4.2 异常与Optional对比
public static Optional<Integer> stringToInt(String s){
	try{return Optional.of(Integer.parseInt(s));}
	catch(NumberFormatException e){return Optional.empty();}
}

//10.4.3 把所有内容整合起来 P218

import org.junit.*;
import java.util.*;	
import static java.util.Optional.*;
import static org.junit.Assert.assertEquals;
public class ReadPositiveIntParam {
	public void testMap() {
		Properties props = new Properties();
		props.setProperty("a", "5");
		props.setProperty("b", "true");
		props.setProperty("c", "-3");
		assertEquals(5, readDurationImperative(props, "a"));
		assertEquals(0, readDurationImperative(props, "b"));
		assertEquals(0, readDurationImperative(props, "c"));
		assertEquals(0, readDurationImperative(props, "d"));	
		assertEquals(5, readDurationWithOptional(props, "a"));
		assertEquals(0, readDurationWithOptional(props, "b"));
		assertEquals(0, readDurationWithOptional(props, "c"));
		assertEquals(0, readDurationWithOptional(props, "d"));
		}
	
public static int readDurationImperative(Properties props, String name) {
	String value = props.getProperty(name);
	if (value != null) {
		try {int i = Integer.parseInt(value);
			if (i > 0) {return i;}
		}
		catch (NumberFormatException nfe) { }
	}
	return 0;
}
	
public static int readDurationWithOptional(Properties props, String name) {
	return ofNullable(props.getProperty(name))
						.flatMap(ReadPositiveIntParam::s2i)
						.filter(i -> i > 0).orElse(0);
	}
	
public static Optional<Integer> s2i(String s) {
	try {return of(Integer.parseInt(s));} 
	catch (NumberFormatException e) {return empty();}
	}
}




----------------------------------------------------------------------------------cp11 CompletableFuture:组合式异步编程
//11.1 Future接口
//实例:use Future
ExecutorService executor=Executors.newChachedThreadPool();
Future<Double> future=executor.submit(new Callable<Double>(){public Double call(){return doSomeLongComputation();}})
doSomethingElse();
try{Double result = future.get(1,TimeUnit.SECONDS);}
catch(ExcutionException ee){}
catch(InterruptedException ie){}
catch(TimeoutException te){}

//11.1.1 Future接口的局限性
//11.1.2 使用CompletableFuture构建异步应用

//11.2实现异步API
public class Shop{public double getPrice(String product){...}}
//实例1:模拟一秒延迟
public static void delay(){
	try{Thread.sleep(1000L);}
	catch(InterruptedException e){throw new RuntimeException(e);}
}
//实例2:
public double getPrice(String product){return calculatePrice(product);}
private double calculatePrice(String product){delay();return random.nextDouble()*product.charAt(0)+product.charAt(1);}

//11.2.1将同步方法转换为异步方法
//实例:
import java.util.concurrent.Future;
public Future<Double> getPriceAsync(String product){...}

//实例:getPriceAsync方法
public Future<Double> getPriceAsync(String product){
	CompletableFuture<Double> futurePrice=new CompletableFuture<>();
	new Thread(()->{double price=calculatePrice(product);
			futurePrice.complete(price);}).start();
	return futurePrice;
}

//实例:使用异步API
Shop shop=new Shop("BestShop");
long start=System.nanoTime();
Future<Double> futurePrice=shop.getPriceAsync("my favorite product");
long invocationTime=((System.nanoTime()-start)/1_000_000);
System.out.println("Invocation returned after "+invocationTime+" msecs")
doSomethingElse();
try{double price=futurePrice.get();
	System.out.printf("Price is %.2f%n",price);}
catch(Exception e){throw new RuntimeException(e);}
long retrievalTime=((System.nanoTime()-start)/1_000_000);
System.out.println("Price returned after "+retrievalTime+" msecs");


//11.2.2 错误处理
public Future<Double> getPriceAsync(String product){
	CompletableFuture<Double> futurePrice=new CompletableFuture<>();
	new Thread(()->{
		try{
			double price=calculatePrice(product);
			futurePrice.complete(price);}
		catch(Exception ex){futurePrice.completeExceptionally(ex);}
		}).start();
	return futurePrice;
}

//实例:使用工厂方法supplyAsync创建CompletableFuture对象
public Future<Double> getPriceAsync(String product){return CompletableFuture.supplyAsync(()->calculatePrice(product));}

//11.3让你的代码免受阻塞之苦
List<Shop> shops=Arrays.asList(new Shop("BetPrice"),new Shop("LetsSaveBig"),new Shop("BigDickShop"),new Shop("Matlab"));
public List<String> findPrices(String product);

//实例:采用顺序查询所有商店的方式实现的findPrices方法
public List<String> findPrices(String product){
	return shops.stream().map(shop->String.format("%s price is %.2f",shop.getName(),shop.getPrice(product))).collect(toList());}

//实例:验证findPrices的正确性和执行性能
long start=System.nanoTime();
System.out.println(findPrices("myPhone27s"));
long duration=(System.nanoTime()-start)/1_000_000;
System.out.println("Done in "+duration+" msecs");

//11.3.1使用并行流对请求进行并行操作
//实例:对findPrices进行并行操作
public List<String> findPrices(String product){
	return shops.parallelStream().map(shop->String.format("%s price is %.2f",shop.getName(),shop.getPrice(product))).collect(toList());
}

//11.3.2 使用CompletableFuture发起异步请求
List<completableFuture<String>> priceFutures=shops.stream().map(shop->CompletableFuture.supplyAsync(()->String.format("%s price is %.2f",shop.getName(),shop.getPrice(product)))).collect(toList());

//使用CompletableFuture实现findPrices方法
public List<String> findPrices(String product){
	List<CompletableFuture<String>> priceFuture=shops.stream().map(shop->CompletableFuture.suppyAsync(()->shop.getName()+" price is "+shop.getPrice(product))).collect(Collectors.toList());
	return priceFutures.stream().map(CompletableFuture::join).collect(Collectors.toList());
}

//11.3.4 使用定制的执行器
//为最优价格查询器应用定制的执行器
private final Executor executor=Executors.newFixedThreadPool(Math.min(shops.size(),100),new ThreadFActory(){
	public Thread newThread(Runnable r){
		Thread t=new Thread(r);
		t.setDaemon(true);
		return t;
	}	
});

CompletableFuture.supplyAsync(()->shop.getName()+" price is "+shop.getPrice(product),executor);

//11.4 对多个异步任务进行流水线操作
import static lambdasinaction.chap11.Util.delay;
import static lambdasinaction.chap11.Util.format;

public class Discount {
    public enum Code {
        NONE(0), SILVER(5), GOLD(10), PLATINUM(15), DIAMOND(20);
        private final int percentage;
        Code(int percentage) {this.percentage = percentage;}
    }
    public static String applyDiscount(Quote quote) {
        return quote.getShopName() + " price is " + Discount.apply(quote.getPrice(), quote.getDiscountCode());
    }
    private static double apply(double price, Code code) {
        delay();
        return format(price * (100 - code.percentage) / 100);
    }
}

//11.4.1 实现折扣服务
public class Quote {
    private final String shopName;
    private final double price;
    private final Discount.Code discountCode;
    public Quote(String shopName, double price, Discount.Code discountCode) {
        this.shopName = shopName;
        this.price = price;
        this.discountCode = discountCode;
    }

    public static Quote parse(String s) {
        String[] split = s.split(":");
        String shopName = split[0];
        double price = Double.parseDouble(split[1]);
        Discount.Code discountCode = Discount.Code.valueOf(split[2]);
        return new Quote(shopName, price, discountCode);
    }

    public String getShopName() {return shopName;}
    public double getPrice() {return price;}
    public Discount.Code getDiscountCode() {return discountCode;}
}

//11.4.2 使用Discount服务
public List<String> findPrices(String product){
	return shop.stream()
			.map(shop->shop.getPrice(product))
			.map(Quote::parse)
			.collect(toList());
}


//11.4.3 构造同步和异步操作
//实例:使用CompletableFuture实现findPrice
public List<String> findPrices(String product){
	List<CompletableFuture<String>> priceFutures=shop.stream()
								.map(shop->CompletableFuture.supplyAsync(()->shop.getPrice(product),executor))
								.map(future->future.thenApply(Quote::parse))
								.map(future->future.thenCompose(quote->CompletableFuture.supplyAsync(()->Discount.applyDiscount(quote),executor))).collect(toList());
	return priceFutures.stream().map(CompletableFuture::join).collect(toList());
}

//P238


//11.4.4 将两个CompletableFuture对象整合起来,无论他们是否存在依赖
//实例:合并两个独立的CompletableFuture对象
Future<Double> futurePriceInUSD=CompletableFuture
			.supplyAsync(()->shop.getPrice(product))
			.thenCombine(CompletableFuture.supplyAsync(()->exchangeService.getRate(Money.EUR,Money.USD)),(price,rate)->price*rate);

//11.4.5 对Future和CompletableFuture的review
//实例:用java7实现合并2个Future对象
ExecutorService executor=Executors.newChachedThreadPool();
final Future<Double> futureRate=executor.submit(new Callable<Double>(){public Double call(){return exchangeService.getRate(Money.EUR,Money.USD);}});
Future<Double> futurePriceInUSD=executor.submit(new Callable<Double>(){
	public Double call(){
		double priceInEUR=shop.getPrice(product);
		return priceInEUR*futureRate.get();
}})


//11.5响应CompletableFuture的completion事件
//实例:模拟一个0.5~2.5s的随机延迟方法
private static final Random random=new Random();
public static void randomDelay(){
	int delay=500+random.nextInt(2000);
	try{Thread.sleep(delay);}
	catch(InterruptedException e){throw new RuntimeException(e);}
}

//11.5.1 对最佳价格查询器应用的优化
//实例:重构findPrices方法返回一个由Future构成的流
public Stream<CompletableFuture<String>> findPricesStream(String product){
	return shops.stream()
			.map(shop->CompletableFuture.supplyAsync(()->shop.getPrice(product),executor))
			.map(future->future.thenApply(Quote::parse))
			.map(future->future.thenCompose(quote->CompletableFuture.supplyAsync(()->Discount.applyDiscount(quote),executor)));
}

//响应CompletableFuture的completion事件
CompletableFuture[] futures=findPricesStream("myPhone")
							.map(f->f.thenAccept(System.out::println))
							.toArray(size->new CompletableFuture[size]);
CompletableFuture.allOf(futures).join();

//11.5.2 付诸实践
long start=System.nanoTime();
CompletableFuture[] futures=findPricesStream("myPhone27s")
							.map(f->f.thenAccept(s->System.out.println(s+" (done in "+((System.nanoTime()-start)/1_000_000)+" msecs)")))
							.toArray(size->new CompletableFuture[size]);
CompletableFuture.allOf(futures).join();
System.out.println("All shops have now responded in "+((System.nanoTime()-start)/1_000_000)+" msecs)");


----------------------------------------------------------------------------------cp12新的日期和时间API
//旧的Data API
Date date=new Date(111,2,18);  <---> 

方法名					返回值类型				对该方法的解释
getYear()				int					获取当前日期的年份
getMonth()				Month					获取当前日期的月份对象
getMonthValue()				int					获取当前日期是第几月
getDayOfWeek()				DayOfWeek				表示该对象表示的日期是星期几
getDayOfMonth()				int					表示该对象表示的日期是这个月第几天
getDayOfYear()				int					表示该对象表示的日期是今年第几天
withYear(int year)			LocalDate				修改当前对象的年份
withMonth(int month)			LocalDate				修改当前对象的月份
withDayOfMonth(int dayOfMonth)		LocalDate				修改当前对象在当月的日期
isLeapYear()				boolean					是否是闰年
lengthOfMonth()				int					这个月有多少天
lengthOfYear()				int					该对象表示的年份有多少天(365或者366)
plusYears(long yearsToAdd)		LocalDate				当前对象增加指定的年份数
plusMonths(long monthsToAdd)		LocalDate				当前对象增加指定的月份数
plusWeeks(long weeksToAdd)		LocalDate				当前对象增加指定的周数
plusDays(long daysToAdd)		LocalDate				当前对象增加指定的天数
minusYears(long yearsToSubtract)	LocalDate				当前对象减去指定的年数
minusMonths(long monthsToSubtract)	LocalDate				当前对象减去注定的月数
minusWeeks(long weeksToSubtract)	LocalDate				当前对象减去指定的周数
minusDays(long daysToSubtract)		LocalDate				当前对象减去指定的天数
compareTo(ChronoLocalDate other)	int					比较当前对象和other对象在时间上的大小,返回值如果为正,则当前对象时间较晚,
isBefore(ChronoLocalDate other)		boolean					比较当前对象日期是否在other对象日期之前
isAfter(ChronoLocalDate other)		boolean					比较当前对象日期是否在other对象日期之后
isEqual(ChronoLocalDate other)		boolean					比较两个日期对象是否相等


//12.1 LocalDate,LocalTime,Instant,Duration以及Period
//12.1.1使用LocalDate和LocalTime
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
public class test {
    public static void main(String[] args){
        Date date=new Date(111,2,18);
        LocalDate date2=LocalDate.of(2018,2,22);
        int year=date2.getYear();
        Month mon=date2.getMonth();
        int day=date2.getDayOfMonth();
        DayOfWeek dow=date2.getDayOfWeek();
        int len=date2.lengthOfMonth();
        boolean leap=date2.isLeapYear();
	LocalDate today=LocalDate.now();
        System.out.println("OLD api : "+date);
        System.out.println("date2 : "+date2 +"\nyear : "+year+"\nmonth : "+mon+"\nday : "+day+"\nDayOfWeek : "+dow+"\nlen : "+len+"\nleap : "+leap);
	System.out.println("now : "+today);
    }
}

//使用TemporalField读取LocalDate的值
int year = date.get(ChronoField.YEAR);
int month = date.get(ChronoField.MONTH_OF_YEAR);
int day = date.get(ChronoField.DAY_OF_MONTH);

//创建LocalTime并读取其值
LocalTime time = LocalTime.of(18,30,22);
int hour = time.getHour();
int min=time.getMinute();
int second=time.getSecond();
//使用parse将字符串转换为时间
LocalDate date=LocalDate.parse("2017-12-22");
LocalTime time=LocalTime.paese("18:22:12");

//12.1.2合并日期和时间
LocalDateTime dt1=LocalDateTime.of(2015,Month.MARCH,13,15,45,22);
LocalDateTime dt2=LocalDateTime.of(dt,tm);
LocalDateTime dt3=date2.atTime(12,22,30);
LocalDateTime dt4=date2.atTime(tm);
LocalDateTime dt5=time.atDate(dt);
System.out.println("dt1: "+ dt1 +" dt2: "+dt2+" dt3: "+dt3+" dt4: "+dt4+" dt5: "+dt5);

LocalDate date1=dt1.toLocalDate();
LocalTime time1=dt1.toLocalTime();


//12.1.3 机器的日期和时间格式
import java.time.Instant;
Instant.ofEpochSecond(3);
Instant.ofEpochSecond(3,0);
Instant.ofEpochSecond(2,1_000_000_000); //2秒之后加上一亿个纳秒
Instant.ofEpochSecond(4,-1_000_000_000);

int day = Instant.now().get(ChronoField.DAY_OF_MONTH);


//12.1.4 定义Duration或Period
Duration d1=Duration.between(time1,time2);
Duration d2=Duration.between(dateTime1,dateTime2);
Duration d3=Duration.between(instant1,instant2);

Period tendays=Period.between(LocalDate.of(2018,9,16),LocalDate.of(2018,9,6));

//实例:创建Duration和Period对象
Duration threeMinutes=Duration.ofMinutes(3);
Duration threeMinutes=Duration.of(3,Chronounit.MINUTES);

Period tendays=Period.ofDays(10);
Period threeWeeks=Period.ofWeeks(3);
Period twoYearsSixMonthsOneDay=Period.of(2,6,1);

#表12-1 日期时间类中表示时间间隔的通用方法
方法名				是否是静态方法				方法描述
between				是					创建2时间点之间的interval
from				是					由一个零时时间点创建interval
of				是					由它的组成部分创建interval实例
parse				是					由字符串创建interval实例
addTo				否					创建该interval副本,并将其叠加到某个temporal对象
get				否					读取该interval状态
isNegative			否					检查该interval是否为负值,不包括零
isZero				否					检查该interval的时长是否为0
minus				否					通过减去一定的时间创建该interval的副本
multipliedBy			否					将interval的值乘以某个标量创建该interval副本
negated				否					以忽略某个时长的方式创建该interval副本
plus				否					以增加某个指定的时长的方式创建该iinterval的副本
substractFrom			否					从指定的temporal对象中减去该interval


//12.2 操纵,解析和格式化日期
LocalDate d1=LocalDate.of(2015,3,22); //2015-03-22
LocalDate d2=d1.withYear(2011);       //2011-03-22
LocalDate d3=d2.withDayOfMonth(25);   //2011-03-25
LocalDate d4=d3.with(ChronoField.MONTH_OF_YEAR,9);  //2011-09-25

//实例:以相对方式修改LocalDate对象的属性
LocalDate d1=LocalDate.of(2015,3,12); //2015-03-12
LocalDate d2=d1.plusWeeks(1);         //2015-03-19
LocalDate d3=d2.minusYears(2);        //2013-03-19
LocalDate d4=d3.plus(6,ChronoUnit.MONTHS);  //2011-09-19

#表12-2 表示时间点的日期-时间类的通用方法
方法名				是否是静态方法				方法描述
from				是					依据传入的Temporal对象创建实例
now				是					依据系统时钟创建Teomporal对象
of				是					由Temporal对象的某个部分创建该对象的实例
parse				是					有字符串创建Temporal对象的实例
atOffset			否					将Temporal对象和某个时区偏移结合
atZone				否					将Temporal对象和某个时区结合
format				否					使用某个指定的格式器将Temporal对象转换为字符串
get				否					读取Temporal对象的某一部分值
minus				否					创建Temporal对象的一个副本,通过将当前的Temporal对象的值减去一定的时长创建该副本
plus				否					创建Temporal对象的一个副本,通过将当前的Temporal对象的值加上一定的时长创建该副本
with				否					以该Temporal对象为模板,对某些状态进行修改创建该对象的副本



//12.2.1使用TemporalAdjuster
//实例:使用预定义的TemporalAdjuster
import static java.time.temporal.TemporalAdjusters.*;
LocalDate d1=LocalDate.of(2014,3,18);				//2014-03-01
LocalDate d2=d1.with(nextOrSame(DayOfWeek.SUNDAY));		//2014-03-23
LocalDate d3=d2.with(lastDayOfMonth());				//2014-03-31

#表12-3 TemporalAdjuster类中的工厂方法
dayOfWeekInMonth 			创建一个新的日期,它的值为同一个月中每一周的第几天
firstDayOfMonth				 创建一个新的日期,它的值为当月的第一天
firstDayOfNextMonth		 	创建一个新的日期,它的值为下月的第一天
firstDayOfNextYear		 	创建一个新的日期,它的值为明年的第一天
firstDayOfYear 				创建一个新的日期,它的值为当年的第一天
firstInMonth				 创建一个新的日期,它的值为同一个月中,第一个符合星期几要求的值
lastDayOfMonth 				创建一个新的日期,它的值为当月的最后一天
lastDayOfNextMonth			 创建一个新的日期,它的值为下月的最后一天
lastDayOfNextYear			创建一个新的日期,它的值为明年的最后一天
lastDayOfYear				创建一个新的日期,它的值为今年的最后一天
lastInMonth				创建一个新的日期,它的值为同一个月中,最后一个符合星期几要求的值
next/previous				创建一个新的日期,并将其值设定为日期调整后或者调整前,第一个符合指定星 期几要求的日期
nextOrSame/previousOrSame		创建一个新的日期,并将其值设定为日期调整后或者调整前,第一个符合指定星期几要求的日期,如果该日期已经符合要求,直接返回该对象 


//实例:TemporalAdjuster接口
public interface TemporalAdjuster{Temporal adjustInto(Temporal temporal);}

//exercise:实现一个定制的TemporalAdjuster
public class NetWorkingDay implements TemporalAdjuster{
	public Temporal adjustInto(Temporal temporal){
		DayOfWeek dow=DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
		int dayToAdd=1;
		if(dow==DayOfWeek.FRIDAY) dayToAdd=3;
		else if(dow==DayOfWeek.SATURADY) dayToAdd=2;
		return temporal.plus(dayToAdd,ChronoUnit.DAYS);
	}
}

--->
date=date.with(temporal->{DayOfWeek dow=DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
			int dayToAdd=1;
			if(dow==DayOfWeek.FRIDAY) dayToAdd=3;
			else if(dow==DayOfWeek.SATURADY) dayToAdd=2;
			return temporal.plus(dayToAdd,ChronoField.DAYS);
		});

--->
TemporalAdjuster nextWorkingDay=TemporalAdjusters.ofDateAdjuster(
	temporal->{
		DayOfWeek dow=DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
		int dayToAdd=1;
		if(dow==DayOfWeek.FRIDAY) dayToAdd=3;
		else if(dow==DayOfWeek.SATURADY) dayToAdd=2;
		return temporal.plus(dayToAdd,ChronoUnit.DAYS);
		});
date=date.with(nextWorkingDay);


//12.2.2 打印输出及解析日期-时间对象
import java.time.format.*;
LocalDate date=LocalDate.of(2014,3,18);
String s1=date.format(DateTimeFormatter.BASIC_ISO_DATE);	//20140318
String s2=date.format(DateTimeFormatter.ISO_LOCAL_DATE);	//2014-03-18

LocalDate date1=LocalDate.parse("20140318",DateTimeFormatter.BASIC_ISO_DATE);
LocalDate date2=LocalDate.parse("2014-03-18",DateTimeFormatter.ISO_LOCAL_DATE);

//实例:按照某个模式创建DateTimeFormatter
DateTimeFormatter formatter=DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDate date1=LocalDate.of(2014,3,18);
String formattedDate=date1.format(formatter);
LocalDate date2=LocalDate.parse(formattedDate,formatter);

//实例:创建一个本地化的DateTimeFormatter
DateTimeFormatter italianForamtter=DateTimeFormatter.ofPattern("d.MMMM yyyy",Local.ITALIAN);
LocalDate date1=LocalDate.of(2014,3,18);
String formattedDate=date.format(italianFormatter);
LocalDate data2=LocalDate.parse(formattedDate,italianFormatter);

//实例:构造一个DateTimeFormatter
DateTimeFormatter italianFormatter=new DateTimeFormatterBuilder()
								.appendText(ChronoFiled.DAY_OF_YEAR)
								.appendLiteral(". ")
								.appendText(ChronoField.YEAR)
								.parseCaseInsensitive()
								.toFormatter(Local.ITALIAN);
//12.3 处理不同的时区和历法
LocalDate date=LocalDate.of(2014,Month.MARCH,18);
ZonedDateTime zdt1=date.atStartOfDay(romeZome);
LocalDateTime dateTime=LocalDateTime.of(2014,Month.MARCH,18,13,45);
ZonedDateTime zdt2=dateTime.atZone(romeZone);
Instant instant=Instant.now();
ZonedDateTime zdt3=instant.atZone(romeZone);

//
LocalDateTime dateTime=LocalDateTime.of(2014,Month.MARCH,18,13,45);
Instant instantFromDateTime=dateTime.toInstant(romeZome);
//
Instant instant=Instant.now();
LocalDateTime timeFromInstant=LocalDateTime.ofInstant(instant,romeZone);


//12.3.1利用UTC/格林尼治时间的固定偏差计算时区
//纽约落后伦敦5小时
ZoneOffset newYorkOffset=ZoneOffset.of("-05:00");
LocalDateTime dateTime=LocalDateTime.of(2014,Month.MARCH,18,13,45);
OffsetDateTime dateTimeInNewYork=OffsetDateTime.of(date,newYorkOffset);

//12.3.2使用别的日历系统 P258
java8还提供了4种日历系统:ThaiBuddhistDate,MinguoDate,JapaneseDate,HijrahDate
LocalDate date=LocalDate.of(2014,Month.MARCH,18);
JapaneseDate japaneseDate=JapaneseDate.from(date);

Chronology japaneseChronology=Chronology.ofLocale(Locale.JAPAN)
ChronolocalDate now=japaneseChronology.dateNow();

//伊斯兰教日历
HijrahDate ramadanDate=HijrahDate.now().with(ChronoField.DAY_OF_MONTH,1).with(ChronoField.MONTH_OF_YEAR,9);
System.out.println("Ramadan starts on "+IsoChronology.INSTANCE.date(ramadanDate)+" and ends on "+IsoChronology.INSTANCE.date(ramadanDate.with(TemporalAdjuster.lastDayOfMonth())));

//package lambdasinaction.chap12;
	
import static java.time.temporal.TemporalAdjusters.lastDayOfMonth;
import static java.time.temporal.TemporalAdjusters.nextOrSame;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Month;
import java.time.chrono.JapaneseDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjuster;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
	
public class DateTimeExamples {
	private static final ThreadLocal<DateFormat> formatters = new ThreadLocal<DateFormat>() {
		protected DateFormat initialValue() {return new SimpleDateFormat("dd-MMM-yyyy");}
	};
	
	public static void main(String[] args) {
		useOldDate();
		useLocalDate();
		useTemporalAdjuster();
		useDateFormatter();
	}
	
	private static void useOldDate() {
		Date date = new Date(114, 2, 18);
		System.out.println(date);
		System.out.println(formatters.get().format(date));
		Calendar calendar = Calendar.getInstance();
		calendar.set(2014, Calendar.FEBRUARY, 18);
		System.out.println(calendar);
	}
	
	private static void useLocalDate() {
		LocalDate date = LocalDate.of(2014, 3, 18);
		int year = date.getYear(); // 2014
		Month month = date.getMonth(); // MARCH
		int day = date.getDayOfMonth(); // 18
		DayOfWeek dow = date.getDayOfWeek(); // TUESDAY
		int len = date.lengthOfMonth(); // 31 (days in March)
		boolean leap = date.isLeapYear(); // false (not a leap year)
		System.out.println(date);
	
		int y = date.get(ChronoField.YEAR);
		int m = date.get(ChronoField.MONTH_OF_YEAR);
		int d = date.get(ChronoField.DAY_OF_MONTH);
	
		LocalTime time = LocalTime.of(13, 45, 20); // 13:45:20
		int hour = time.getHour(); // 13
		int minute = time.getMinute(); // 45
		int second = time.getSecond(); // 20
		System.out.println(time);
	
		LocalDateTime dt1 = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45, 20); // 2014-03-18T13:45
		LocalDateTime dt2 = LocalDateTime.of(date, time);
		LocalDateTime dt3 = date.atTime(13, 45, 20);
		LocalDateTime dt4 = date.atTime(time);
		LocalDateTime dt5 = time.atDate(date);
		System.out.println(dt1);
	
		LocalDate date1 = dt1.toLocalDate();
		System.out.println(date1);
		LocalTime time1 = dt1.toLocalTime();
		System.out.println(time1);
	
		Instant instant = Instant.ofEpochSecond(44 * 365 * 86400);
		Instant now = Instant.now();
	
		Duration d1 = Duration.between(LocalTime.of(13, 45, 10), time);
		Duration d2 = Duration.between(instant, now);
		System.out.println(d1.getSeconds());
		System.out.println(d2.getSeconds());
	
		Duration threeMinutes = Duration.of(3, ChronoUnit.MINUTES);
		System.out.println(threeMinutes);
	
		JapaneseDate japaneseDate = JapaneseDate.from(date);
		System.out.println(japaneseDate);
	}
	
	private static void useTemporalAdjuster() {
		LocalDate date = LocalDate.of(2014, 3, 18);
		date = date.with(nextOrSame(DayOfWeek.SUNDAY));
		System.out.println(date);
		date = date.with(lastDayOfMonth());
		System.out.println(date);
	
		date = date.with(new NextWorkingDay());
		System.out.println(date);
		date = date.with(nextOrSame(DayOfWeek.FRIDAY));
		System.out.println(date);
		date = date.with(new NextWorkingDay());
		System.out.println(date);
	
		date = date.with(nextOrSame(DayOfWeek.FRIDAY));
		System.out.println(date);
		date = date.with(temporal -> {
			DayOfWeek dow = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
			int dayToAdd = 1;
			if (dow == DayOfWeek.FRIDAY) dayToAdd = 3;
			if (dow == DayOfWeek.SATURDAY) dayToAdd = 2;
			return temporal.plus(dayToAdd, ChronoUnit.DAYS);
		});
		System.out.println(date);
	}
	
	private static class NextWorkingDay implements TemporalAdjuster {
		public Temporal adjustInto(Temporal temporal) {
			DayOfWeek dow = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
		int dayToAdd = 1;
		if (dow == DayOfWeek.FRIDAY) dayToAdd = 3;
		if (dow == DayOfWeek.SATURDAY) dayToAdd = 2;
		return temporal.plus(dayToAdd, ChronoUnit.DAYS);
		}
	}
	
	private static void useDateFormatter() {
		LocalDate date = LocalDate.of(2014, 3, 18);
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
		DateTimeFormatter italianFormatter = DateTimeFormatter.ofPattern("d. MMMM yyyy", Locale.ITALIAN);
	
		System.out.println(date.format(DateTimeFormatter.ISO_LOCAL_DATE));
		System.out.println(date.format(formatter));
		System.out.println(date.format(italianFormatter));
	
		DateTimeFormatter complexFormatter = new DateTimeFormatterBuilder()
										.appendText(ChronoField.DAY_OF_MONTH)
										.appendLiteral(". ")
										.appendText(ChronoField.MONTH_OF_YEAR)
										.appendLiteral(" ")
										.appendText(ChronoField.YEAR)
										.parseCaseInsensitive()
										.toFormatter(Locale.ITALIAN);
		System.out.println(date.format(complexFormatter));
	}
	
}


---Part4 超越JAVA8
----------------------------------------------------------------------------------cp13 函数式思考
//13.1 实现和维护系统								
//13.1.1 共享的可变数据
不可变对象一旦完成初始化就不会被任何方法修改状态。可以共享,线程安全的。
//13.1.1 共享的可变数据
不可变对象一旦完成初始化就不会被任何方法修改状态。可以共享,线程安全的。
//实例
Transaction mostExpensive=transactions.get(0);
if(mostExpensive==null)throw new IllegalArgumentException("Empty list of transactions")
for(Transaction t:transactions.subList(1,transactions.size())){if(t.getValue()>mostExpensive.getValue){mostExpensive=t;}}

===>
Optional<Transaction> mostExpensive=transactions.stream().max(comparing(Transaction::getValue));

//13.1.3 为什么要采用函数式编程
函数式编程具体实践了前面介绍的声明式编程和无副作用计算。

//13.2 什么是函数式编程=
它是一种使用函数进行编程的方式。
当谈论函数式时,我们想说的其实是“像数学函数那样——没有副作用”。

//13.2.2 引用透明性
“没有可感知的副作用”的这些限制都隐含着引用透明性。如果一个函数只要传递同样的参数值,总是返回同样的结果,那这个函数就是引用透明的。
在函数式编程中,你应该选择使用引用透明的函数。

//13.2.3 面向对象的编程和函数式编程的对比
//13.2.4函数式编程实战
//实例:子集
static List<List<Integer>> subsets(List<Integer> list){
	if(list.isEmpty()){
		List<List<Integer>> ans=new ArrayList<>();
		ans.add(Collections.emptyList());
		return ans;
	}
	Integer first = list.get(0);
	List<List<Integer>> subans=subsets(rest);
	List<List<Integer>> subans2=insertAll(first,subans);
	return concat(suban,subans);
}

//
static List<List<Integer>> insertAll(Integer first,List<List<Integer>> lists){
	List<List<Integer>> result = new ArrayList<>();
	for(List<Integer> list:lists){
		List<Integer> copyList=new Arraylist<>();
		copyList.add(first);
		copyList.addAll(list);
		result.add(copyList);
	}
	return result;
}

<===>
static List<List<Integer>> concat(List<List<Integer>> a,List<List<Integer>> b){
	a.addAll(b);
	return a;
}
--->
static List<List<Integer>> concat(List<List<Integer>> a,List<List<Integer>> b){
	List<List<Integer>> r=new ArrayList<>(a);
	r.addAll(b);
	return r;
}


//13.3 递归和迭代
Iterator<Apple> it = apples.iterator();
while (it.hasNext()){Apple apple = it.next();}
public void searchForGold(List<String> l,Stats stats){for(String s:l){if("gold".equals(s)){stats.incrementFor("gold");}}}

//实例:迭代阶乘计算
static int factorialIterative(int n) {
	int r = 1;
	for(int i = 1; i <=n; i++) {r *= i;}
	return r;
}

//递归式的阶乘计算
static long factorialRecursive(long n) {return n == 1 ? 1 : n * factorialRecursive(n-1);}

//基于Stream的阶乘
static long factorialStreams(long n) {return LongStream.rangeClosed(1,n).reduce(1,(long 1,long b) -> a * b);}

//基于“尾-递”的阶乘
static long factorialTailRecursive(long n) {return factorialHelper(1,n);}
static long factorialHelper(long acc,long n) {return n == 1 ? acc : factorialHelper(acc * n, n-1);}

----------------------------------------------------------------------------------cp14 函数式编程技巧
//14.1 无处不在的函数
//14.1.1 高阶函数
Comparator<Apple> c=comparing(Apple::getWeight);
Function<String,String> transformationPipeline=addHeader.andThen(Letter::checkSpelling).andThen(Letter::addFooter);

特征(满足其一即可)
1. 接受至少一个函数作为参数
2. 返回结果是一个函数

//14.1.2 科里化(多函数参数单一化)
static double converter(double x,double f,double b){return x*f+b;}
--->
static DoubleUnaryOperator curriedConverter(double f,double b){return (double x)->x*f+b; }

//14.2 持久化的数据结构 p278
//14.2.1 破坏式更新和函数式更新的比较
class TrainJourney{
	public int price;
	public TrainJourney onward;
	public TrainJourney(int p,TrainJourney t){
		price = p;
		onward=t;
	}
}
//将TrainJourney对象链接起来
static TrainJourney link(TrainJourney a,TrainJourney b){
	if (a==null) return b;
	TrainJourney t=a;
	while (t.onward !=null){t=t.onward;}
	t.onward=b;
	return a;
}

--->
static TrainJourney append(TrainJourney a,TrainJourney b){return a==null ? b:new TrainJourney(a.price,append(a.onward,b));}

//14.2.2 另一个使用Tree的例子
//实例:二叉树
class Tree{
	private String key;
	private int val;
	private Tree left,right;
	public Tree(String k,int v,Tree l,Tree k){key=k;val=v,left=l;right=r;}
}
class TreeProcessor{
	public static int lookup(String k,int defaultval,Tree t){
		if(t==null) return defaultval;
		if(k.equals(t.key)) return t.val;
		return lookup(k,defaultval,k.compareTo(t.key)<0 ? t.left:t.right);
	}
}

~~~>looking for something

public static void update(String k,int newval,Tree t){
	if(t==null) {/* ... */};
	else if(k.equals(t.key)) t.val=newval;
	else update(k,newval,k.compareTo(t.key)<0 ? t.left:t.right);	
}

//创建新树节点
public static Tree update(String k,int newval,Tree t){
	if(t==null) t=new Tree(k,newval,null,null);
	else if (k.equals(t.key)) t.val=newval;
	else if (k.compareTo(t.key)<0) t.left=update(k,newval,t.left);
	else t.right=update(k,neval,t.right);
	return t;
}


//14.2.3 采用函数式的方法
public static Tree fupdate(String k,int newval,Tree t){
	return (t==null) ?
		new Tree(k,newval,null,null):
			k.equals(t.key) ?
				new Tree(k,newval,t.left,t.right):
			k.compareTo(t.key)<0 ?
				new Tree(t.key,t.val,fupdate(k,newval,t.left),t.right):
				new Tree(t.key,t.val,t.left,fupdate(k,newval,t.right));
}


//14.3 Stream的延迟计算
//14.3.1 自定义Stream P283
//
public static Stream<Integer> primes(int n){return Stream.iterate(2,i->i+1).filter(MyMathUtils::isPrime).limit(n);}
public static boolean isPrime(int candidate){
	int candidateRoot=(int) Math.sqrt((double) candidate);
	return IntStream.rangeClosed(2,candidateRoot).noneMatch(i->candidate%i==0);
}

1: 构造由数字组成的Stream
static IntStream numbers(){return IntStream.iterate(2,n->n+1);}

2: 取得首元素
static int head(IntStream numbers){return numbers.findFirst().getAsInt();}

3: 对尾部元素进行筛选
static IntStream tail(IntStream numbers){return numbers.skip(1);}

IntStream numbers =numbers();
int head = head(numbers);
IntStream filtered=tail(numbers).filter(n->n%head !=0);

4: 递归地创建有质数组成的Stream
static IntStream primes(IntStream numbers){
	int head =head(numbers);
	return IntStream.concat(IntStream.of(head),primes(tail(numbers).filter(n->n%head !=0)));
}

5: bad news

6:延迟计算

//14.3.2 创建你自己的延迟列表

1.一个基本的链接列表
interface MyList<T>{
	T head();
	MyList<T> tail();
	default boolean isEmpty(){return true;}
}

class MyLinkedList<T> implements MyList<T>{
	private final T head;
	private final MyList<T> tail;
	public MyLinkedList<T head,MyList<T> tail>{
		this.head=head;
		this.tail=tail;
	}
	public T head(){return head;}
	public MyList<T> tail(){return tail;}
	public boolean isEmpty(){return false;}
}

class Empty<T> implements MyList<T>{
	public T head(){throw new UnsupportedOperationException();}
	public MyList<T> tail(){throw new UnsupportedOperationException();}
}

2. 一个基础的延迟列表
import java.util.function.Supplier;
class LazyList<T> implements MyList<T>{
	final T head;
	final Supplier<MyList<T>> tail;
	public LazyList(T head,Supplier<MyList<T>> tail){this.head=head;this.tail=tail;}
	public T head(){return head;}
	public MyList<T> tail(){return tail.get();}
	public boolean isEmpty(){return false;}
}

public static LazyList<Integer> from(int n){return new LazyList<Integer>(n,()->from(n+1));}

LazyList<Integer> numbers=from(2);
int two =numbers.head();
int three=numbers.tail().head();
int four=numbers.tail().tail().head();
System.out.println(two+" "+three+" "+four);

3. 回到生成质数
public static MyList<Integer> primes(MyList<Integer> numbers){
	return new LazyList<Integer>(numbers.head(),()->primes(numbers.tail().filter(n->n % numbers.head() !=0)));
}

4. 实现以恶搞延迟筛选器
public MyList<T> filter(Predicate<T> p){
	return isEmpty ? 
		this:p.test(head()) ? 
			new LazyList<>(head(),()->tail().filter(p)):tail().filter(p);
}

--->
LazyList<Integer> numbers=from(2);
int two = primes(numbers).head();
int three=primes(numbers).tail().head();
int five=primes(numbers).tail().tail().head();
System.out.println(two+" "+three+" "+five);

--->
static <T> void printAll(MyList<T> list){while(!list.isEmpty()){System.out.println(list.head());list=list.tail();}}
printAll(primes(from(2)));

--->
static <T> void printAll(MyList<T> list){
	if(list.isEmpty())
		return;
	System.out.println(list.head());
	printAll(list.tail());
}

5. 何时使用


//14.4 匹配模式 P290
//14.4.1 访问者设计模式
class BinOp extends Expr{
	...
	public Expr accept(SimplifyExprVisitor v){return v.visit(this);}
}

public class SimplifyExprVisitor{
	...
	public Expr visit(BinOp e){if("+".equals(e.opname) && e.right instanceof Number &&...){return e.left;}}
}


//14.4.2 用匹配模式力挽狂澜
def simplifyExpression(expr:Expr):Expr = expr match{
	case BinOp("+",e,Number(0))=>e	//加0
	case BinOp("*",e,Number(1))=>e	//乘以1
	case BinOp("/",e,Number(1))=>e	//除以1
	case _=>expr			//不能简化expr
}

//实例:使用模式匹配简化表达式 P294
public static Expr simplify(Expr e){
	TriFunction<String,Expr,Expr,Expr> binopcase=
		(opname,left,right)->{
				if("+".equals(opname)){if(left instanceof Number &&((Number) left).val==0){return right;}
							if(right instanceof Number &&(Number right).val==0){return left;}
							}
				if("*".equals(opname)){if(left instanceof Number &&((Number) left).val==1){return right;}
							if(right instanceof Number &&(Number right).val==1){return left;}
							}
				return new BinOp(opname,left,right);
				};
	Function<Integer,Expr> numcase=val->new Number(val);
	Supplier<Expr> defaultcase=()->new Number(0);
	return patternMatchExpr(e,binopcase,numcase,defaultcase);
}

//14.5 杂项
//14.5.1缓存或记忆表
final Map<Range,Integer> numberOfNodes=new HashMap<>();
Integer computeNumberOfNodesUsingCache(Range range){
	Integer result = numberOfNodes.get(range);
	if(result !=null){return result;}
	result = computeNumberOfNodes(range);
	numberOfNodes.put(range,result);
	return result;
}

//14.5.2 "返回同样的对象"意味着什么?
//14.5.3 结合器p296

----------------------------------------------------------------------------------cp15 面向对象和函数式编程额混合:Java8和Scala的比较
//15.1 scala简介
//15.1.1 hello bear
1.命令式Scala
object Beer{
  def main(args:Array[String]){
    var n : Int=2
    while (n<=6){
      println(s"hello ${n} bottles of beer")
      n+=1
    }
  }
}

2.函数式Scala
public class Foo{
	public static void main(String[] args){IntStream.rangeClosed(2,6).forEach(n->System.out.println("Hello "+n+" bottles of beer"));}
}

--->
object Beer{
  def main(args:Array[String]){
    2 to 6 foreach{n=>println(s"hello ${n} bottles of beer")} //2.to(6)
  }
}


//15.1.2 基础数据结构:List,Set,Map,Tuple,Stream,Option
1.创建集合 
---by scala
val authorsToAge=Map("diss"->15,"rose"->18,"jarx"->22)
---by java
Map<String,Integer> authorsToAge=new HashMap<>();
authorsToAge.put("diss",15);
authorsToAge.put("rose",18);
authorsToAge.put("jarx",22);

val authors=List("diss","rose","jarx")
val numbers=Set(1,2,1,2,3,4)


2. 不可变与可变的比较
//在scala中,集合时不可变的
val numbers=Set(2,1,4)
val newNumber=numbers+8
println(newNumbers)			--->(2,1,4,8)
println(numbers)			--->(2,1,4)


3.使用集合
val fileLines=Source.from("data.txt").getLines.toList()
val linesLongUpper=fileLines.filter(l=>l.length>10),map(l=>l.toUpperCase())
===>
val linesLongUpper=fileLines filter (_.length>10) map (_.toUpperCase())

//parallel调用
--->
val linesLongUpper=fileLines.par filter (_.length>10) map (_.toUpperCase())


4.元组
---java
public class Pair<X,Y>{
	public final X x;
	public final Y y;
	public Pair(X x,Y y){this.X=x;this.Y=y;}
}

Pair<String,String> raoul=new Pair<>("Raoul","+10086 11 ");
Pair<String,String> raoul=new Pair<>("Alan","+100666 11 ");

---scala
val roual=("Raoul","+10086 11 ")
val alan=("Alan","+100666 11 ")
val book=(2018,"harry port and his bitches","pron")
val numbers=(1,2,3,1,2,3,222,12,323,1,3423)


5.Stream P305

6.Option
//实例:getCarInsuranceName
---by java
public String getCarInsuranceName(Optional<Person>,int minAge){
	return person.filter(p->p.getAge>=minAge)
			.flatMap(Person::getCar)
			.flatMap(Car::getInsurance)
			.map(Insurance::getName)
			.orElse("Unknown");
}

---by scala
def getCarInsuranceName(person:Option[person],minAge:Int)=person
								.filter(_.getAge()>=minAge)
								.flatMap(_.getCar)
								.flatMap(_.getInsurance)
								.map(_getName).getOrElse("Unknown")
//scala 中不传入参数 方法元括号可以省略


//15.2 函数 P306
//15.2.1 Scala中的一等函数
//筛选函数:是否包含Java字眼&length>20
def isJavaMentioned(tweet:String):Boolean=tweet.contains("Java")
def isShortTweet(tweet:String):Boolea=tweet.length()<20
---应用函数
val tweets=List("this is a fucking booke of Java","that was fucking good","i like scala more than java")
tweets.filter(isJavaMentioned).foreach(println)
tweets.filter(isShortTweet).foreach(println)
-<内嵌方法函数签名>-
def filter[T](p:(T)=>Boolean):List[T]


//15.2.2 匿名函数和闭包
val isLongTweet : String => Boolean = (tweet : String) => tweet.length()>60
//apply 实现
val isLongTweet : String = new Function1[String,Boolean]{def apply(tweet:String):Boolean=tweet.length()>60}
isLongTweet.apply("A very short sweet")

--by java
Function<String,Boolean> isLongTweet=(String s)->s.length()>60;
boolean long = isLongTweet.apply("A very short sweet");

#闭包 p308
def main(args:Array[String]){
	var count=0
	val inc=()=>count+=1
	inc()
	println(count)
	inc()
	println(count)
}

//15.2.3 科里化
//示例:
--by java
static int multiply(int x,int y){return x*y;}
static Function<Integer,Integer> multiplyCurry(int x){return (Integer y)->x*y;}
stream.of(1,3,5,7).map(multiplyCurry(2)).forEach(System.out::println);

--by scala
def multiply(x:Int,y:Int)=x*y
var r=multiply(2,10)

//调用科里化函数
def multiplyCurry(x:Int)(y:Int)=x*y
var r=multiplyCurry(2)(10)


//15.3 类和Trait
//15.3.1 更加简洁的Scala类
class hello{def sayThankYou(){println("Thanks for reading our book")}}
val h=new hello()
h.sayThankYou()

//getter方法和setter方法
//实例:
public class Student{
	private String name;
	private int id;
	public Student(String name){this.name=name;}
	public String getName(){return name;}
	public void setName(String name){this.name=name.}
	public int getId(){return id;}
	public void setId(int id){this.id=id;}
}

--->by scala
class Student(var name:String,var id:Int)
val s=new Student("Raoul",l)
println(s.name)
s.id=1337
println(s.id)


//15.3.2 Scala的trait与Java8的接口对比
trait Sized{
	var size:Int=0
	def isEmpty()=size==0
}

class Empty extends Sized
println(new Empty().isEmpty())

class Box
vsl b1=new Box() with size
println(b1.isEmpty())
val b2=new Box()
b2.isEmpty()



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值