Java8-001

275 阅读14分钟

Java8文章

Android/AS对Java8的支持

Java8示例

public class T1 {
	public static void main(String[] args) {
		T1 t = new T1();
		// t.f1();
		// t.f1t1();
		// t.f2();
		// t.f3();
		//t.f4();
		//t.f5();
		//t.f6();
		//t.f7();
		//t.f8();
		//t.f9();
		//t.f10();
		//t.f11();
		//t.fCompoundLambda();
		//t.streamUse();
		//t.streamAndCollection();
		//t.streamAndOpt();
		//t.streamDistinct();
		//t.streamSkip();
		//t.streamFlatMap();
		//t.streamMatch();
		//t.streamFind();
		//t.streamReduce();
		//t.streamCreate();
		//t.StreamCollectors();
		//t.StreamCollectors();
		t.OptionalUse();
	}

	public void f1() {
		List<Person> list = Arrays.asList(new Person(10, 10), new Person(11, 11), new Person(30, 30),
				new Person(12, 12));
		Collections.sort(list, new Comparator<Person>() {
			@Override
			public int compare(Person o1, Person o2) {
				// return o1.getWeight() - o2.getWeight();
				return ((Integer) o1.getWeight()).compareTo((Integer) o2.getWeight());
			}
		});
		for (Person item : list) {
			System.out.println("Persion info:" + item);
		}
	}

	/**
	 * Comparator.comparing
	 */
	public void f1t1() {
		List<Person> list = Arrays.asList(new Person(10, 10), new Person(11, 11), new Person(30, 30),
				new Person(12, 12));
		list.sort(Comparator.comparing(Person::getWeight));
		for (Person item : list) {
			System.out.println("Persion info:" + item);
		}
	}

	public boolean isOld(Fruit fruit) {
		return Integer.parseInt(fruit.getName()) <= 3;
	}

	public boolean isLow(Fruit fruit) {
		return fruit.getPrice() < 10;
	}

	public List<Fruit> filterFruit(List<Fruit> fruits, Predicate<Fruit> p) {
		List<Fruit> result = new ArrayList<>();
		for (Fruit item : fruits) {
			if (p.test(item)) {
				result.add(item);
			}
		}
		return result;
	}

	/**
	 * Predicate的使用 及 Lambd表达式的使用
	 */
	public void f2() {
		List<Fruit> ori = Arrays.asList(new Fruit("1", 1), new Fruit("2", 2), new Fruit("3", 20), new Fruit("4", 8));
		// 1:单独创建指定类型参数的函数,做为Predicate参数传入指定方法
//		System.out.println("old Fruit:");
//		List<Fruit> old = filterFruit(ori, this::isOld);
//		for(Fruit item:old) {
//			System.out.println("Fruit info:"+item);
//		}
//		System.out.println();
//		System.out.println("low Fruit:");
//		List<Fruit> low = filterFruit(ori, this::isLow);
//		for(Fruit item:low) {
//			System.out.println("Fruit info:"+item);
//		}

		// 2:使用Lambda直接创建Predicate实例作为参数传入指定方法
		System.out.println("old Fruit:");
		List<Fruit> old = filterFruit(ori, (Fruit f) -> Integer.parseInt(f.getName()) <= 3);
		for (Fruit item : old) {
			System.out.println("Fruit info:" + item);
		}
		System.out.println();
		System.out.println("low Fruit:");
		List<Fruit> low = filterFruit(ori, (Fruit f) -> f.getPrice() < 10);
		for (Fruit item : low) {
			System.out.println("Fruit info:" + item);
		}
	}

	/**
	 * 试验 Interface 的默认方法 Interface的默认方法,其实现类可以不重写.实现按需重写.避免普通接口方法必须重写的问题.
	 */
	public void f3() {
		Imp1 imp = new Imp1();
		imp.df1();
	}

	private List<Fruit> gainFruits() {
		List<Fruit> fruits = Arrays.asList(new Fruit("1", 1), new Fruit("6", 6), new Fruit("3", 3), new Fruit("10", 10),
				new Fruit("2", 2));
		return fruits;
	}

	/**
	 * 替代匿名类
	 */
	public void f4() {
		// 原始写法
		List<Fruit> fruits = gainFruits();
		Collections.sort(fruits, new Comparator<Fruit>() {
			@Override
			public int compare(Fruit o1, Fruit o2) {
				return o1.getPrice() > o2.getPrice() ? 1 : (o1.getPrice() == o2.getPrice() ? 0 : -1);
			}
		});
		System.out.println("原始写法:");
		for (Fruit item : fruits) {
			System.out.println(item);
		}
		// 仅保留(o1,o2)
		System.out.println("仅保留(o1,o2):");
		fruits = gainFruits();
		Collections.sort(fruits,
				(o1, o2) -> o1.getPrice() > o2.getPrice() ? 1 : (o1.getPrice() == o2.getPrice() ? 0 : -1));
		for (Fruit item : fruits) {
			System.out.println(item);
		}
		// 使用 Comparator.comparing
		System.out.println("Comparator.comparing:");
		fruits = gainFruits();
		Collections.sort(fruits, Comparator.comparing(Fruit::getPrice));
		for (Fruit item : fruits) {
			System.out.println(item);
		}
		// 直接使用 list.sort
		System.out.println("直接使用 list.sort:");
		fruits = gainFruits();
		fruits.sort(Comparator.comparing(Fruit::getPrice));
		for (Fruit item : fruits) {
			System.out.println(item);
		}
	}
	private interface i1{
		void f1(Object object);
	}
	public void testLambdaReturn(List<Integer> objs,i1 i1) {
		for(Object obj : objs) {
			System.out.println("obj is? before:" + obj);
			i1.f1(obj);
			System.out.println("obj is? after:" + obj);
		}
	}
	/**
	 *	Lambda表达式
	 * 	Lambda表达式构成: 	(参数) -> 主体
	 * 	例子: (o1,o2) -> o1.attr2 == o2.attr1
	 * 	Lambda表达式没有return语句,但已经隐含了return.
	 * 
	 * 	Java8 lambda表达式使用的局部变量是final的/是原始变量的拷贝,不允许修改:
	 * 	https://blog.csdn.net/qq_38345296/article/details/103871684
	 * 	https://blog.csdn.net/reggergdsg/article/details/103287400
	 * 	https://www.zhihu.com/question/361639494
	 * 	在访问自由局部变量时,实际上是在访问它的副本,而不是访问原始变量
	 */
	public void f5() {
		List<Integer> objs = Arrays.asList(1,2,3,4,5);
		testLambdaReturn(objs, (obj) -> {obj = 0;});
	}
	
	interface functionalInterface{
		void f();
	}
	interface functionalInterface1{
		void f1();
		void f2();
	}
	public void testFI(functionalInterface fi) {
		fi.f();
	}
	public void testFI1(functionalInterface1 fi1) {
		fi1.f2();
	}
	
	/**
	 * 	函数式接口就是只定义一个抽象方法的接口.
	 * 	注: 仅仅包含1个抽象接口.
	 * 
	 * 	Lambda 表达式可以允许直接以内联的形式为函数式接口的抽象方法提供实现,并把整个表达式作为函数式接口的实例.
	 */
	public void f6() {
		Runnable r1 = new Runnable() {
			@Override
			public void run() {
				System.out.println("r1.run");
			}
		};
		r1.run();
		Runnable r2 = () -> System.out.println("r2.run");
		r2.run();
		//testFI1(() - > System.out.println(""));	//报错:必须是函数式接口:只有1个抽象函数的接口
		testFI(() -> System.out.println("Lambda表达式直接创建函数式接口实例"));
	}
	
	private List gainList() {
		return Arrays.asList(1,2,3,4,5);
	}
	private void f71(List items, Predicate p) {
		for(Object item:items) {
			if(p.test(item)) {
				System.out.println("f71. pass. item:" + item);
			}
		}
	}
	private void f72(List items, Consumer c) {
		for(Object item:items) {
			c.accept(item);
		}
	}
	private void f73(List items, Function f) {
		int hashCode;
		for(Object item:items) {
			hashCode = Integer.parseInt(f.apply(item).toString()) + 10;
			System.out.println("f73. hashCode:" + hashCode);
		}
	}
	private void f74(List items, Supplier s) {
		Object result;
		for(Object item:items) {
			result = s.get();
			System.out.println("f74. result:" + result);
		}
	}
	/**
	 * 	使用函数式接口
	 * 	函数式接口包括:
	 * 		Predicate:	1个参数,返回boolean:	传入T,返回boolean.
	 * 		Consumer: 	1个参数,返回Void:	传入T,消费,无返回值.
	 * 		Function:	1个参数,返回任意类型:	传入T,返回任意类型.
	 * 		Supplier:	无参数,返回任意类型:	无参数,返回任意类型.
	 */
	public void f7() {
		List list = gainList();
//		f71(list,(T) -> true);
//		f72(list,(T) -> System.out.println("hashCode:" + T.hashCode()));
//		f73(list,(T) -> T.hashCode());
//		f74(list,() -> Math.random() * 100);
		f71(list,T -> true);
		f72(list,T -> System.out.println("hashCode:" + T.hashCode()));
		f73(list,T -> T.hashCode());
		f74(list,() -> Math.random() * 100);
	}
	
	interface i81{
		void f();
	}
	interface i82{
		void f();
	}
	interface i83{
		void f(Object p1,Object p2);
	}
	private void f8FI(i81 i81) {
		i81.f();
		System.out.println("f8FI. i81");
	}
	private void f8FI(i82 i82) {
		i82.f();
		System.out.println("f8FI. i82");
	}
	private void f8FI(i83 i83) {
		i83.f(1, 2);
	}
	/**
	 * 	使用Lambda表达式,自动执行对应的重载的函数
	 */
	public void f8() {
		//f8FI(() -> {});	//会报错,因为f8FI的2个重载函数,i81 和 i82 中方法参数完全一致,无法区分.
		f8FI((p1,p2) -> System.out.println("i83 结果:" + (p1.hashCode() + p2.hashCode())));
	}
	private int num = 10;
	public void f9() {
		Runnable runnable = () -> num = 20;
		runnable.run();
		System.out.println("num:" + num);
	}
	public void f10t(Consumer<Person> consumer,Person person) {
		consumer.accept(person);
	}
	/**
	 * 
	 * 	Person [age=100, weight=100]
	 *	Person [age=10, weight=200]
	 */
	public void f10() {
		//可以修改lambda表达式传入参数的属性
		Person p = new Person(10,200);
		f10t(P -> {P.age = 100; P.weight = 100;}, p);
		System.out.println(p);
		//但是无法对lambda表达式传输参数重新赋值
		Person p1 = new Person(10,200);
		f10t(P -> P = new Person(300, 300), p1);
		System.out.println(p1);
	}
	private Person createPerson() {
		Person p = new Person((int) (Math.random() * 10000), (int) (Math.random() * 10000));
		return p;
	}
	/**
	 * 	原始Person集合:
		Person [age=4853, weight=1793]
		Person [age=2274, weight=7403]
		Person [age=8586, weight=2709]
		Person [age=307, weight=8623]
		Person [age=6748, weight=6765]
		Person [age=3409, weight=1404]
		最终Age集合
		4853
		2274
		8586
		307
		6748
		3409
	 */
	public void f11() {
		List<Person> persons = Arrays.asList(createPerson(),createPerson(),createPerson(),createPerson(),createPerson(),createPerson());
		System.out.println("原始Person集合:");
		persons.forEach(P -> System.out.println(P));
		List<Integer> ages = persons.stream().map(Person::getAge).collect(Collectors.toList());
		System.out.println("最终Age集合");
		ages.forEach(A -> System.out.println(A));
	}
	/**
	 * 	复合Lambda表达式
	 * 
	 * 	按照年龄升序排列:
		Person [age=2166, weight=7086]
		Person [age=2834, weight=2782]
		Person [age=3620, weight=5036]
		Person [age=4000, weight=666]
		Person [age=4000, weight=667]
		Person [age=4000, weight=668]
		Person [age=4000, weight=669]
		Person [age=4046, weight=310]
		Person [age=4445, weight=708]
		Person [age=5017, weight=5820]
		Person [age=6012, weight=8375]
		Person [age=9429, weight=8925]
		按照年龄降序排列:
		Person [age=9429, weight=8925]
		Person [age=6012, weight=8375]
		Person [age=5017, weight=5820]
		Person [age=4445, weight=708]
		Person [age=4046, weight=310]
		Person [age=4000, weight=666]
		Person [age=4000, weight=667]
		Person [age=4000, weight=668]
		Person [age=4000, weight=669]
		Person [age=3620, weight=5036]
		Person [age=2834, weight=2782]
		Person [age=2166, weight=7086]
		先按照年龄升序排列,再按照体重降序排列
		Person [age=2166, weight=7086]
		Person [age=2834, weight=2782]
		Person [age=3620, weight=5036]
		Person [age=4000, weight=669]
		Person [age=4000, weight=668]
		Person [age=4000, weight=667]
		Person [age=4000, weight=666]
		Person [age=4046, weight=310]
		Person [age=4445, weight=708]
		Person [age=5017, weight=5820]
		Person [age=6012, weight=8375]
		Person [age=9429, weight=8925]
		年龄不大于5000:
		Person [age=2166, weight=7086]
		Person [age=2834, weight=2782]
		Person [age=3620, weight=5036]
		Person [age=4000, weight=669]
		Person [age=4000, weight=668]
		Person [age=4000, weight=667]
		Person [age=4000, weight=666]
		Person [age=4046, weight=310]
		Person [age=4445, weight=708]
		年龄大于5000且体重大于2000
		Person [age=5017, weight=5820]
		Person [age=6012, weight=8375]
		Person [age=9429, weight=8925]
		年龄大于5000或体重大于2000
		Person [age=2166, weight=7086]
		Person [age=2834, weight=2782]
		Person [age=3620, weight=5036]
		Person [age=5017, weight=5820]
		Person [age=6012, weight=8375]
		Person [age=9429, weight=8925]
		试验Function复合函数
		18
		10
	 */
	public void fCompoundLambda() {
		//1:比较器复合
//		List<Person> persons = Arrays.asList(
//				createPerson(),createPerson(),createPerson(),createPerson(),createPerson(),createPerson(),
//				createPerson(),createPerson(),createPerson(),createPerson(),createPerson(),createPerson()
//				);
		List<Person> persons = Arrays.asList(
				createPerson(),createPerson(),createPerson(),createPerson(),createPerson(),createPerson(),
				new Person(4000, 666),new Person(4000, 667),new Person(4000, 668),new Person(4000, 669),createPerson(),createPerson()
				);
		//按照年龄升序
		persons.sort(Comparator.comparing(Person::getAge));
		System.out.println("按照年龄升序排列:");
		persons.forEach(p -> System.out.println(p));
		//按照年龄降序
		persons.sort(Comparator.comparing(Person::getAge).reversed());
		System.out.println("按照年龄降序排列:");
		persons.forEach(p -> System.out.println(p));
		//先按照年龄升序, 再按照体重降序
		persons.sort(Comparator.comparing(Person::getAge).thenComparing(Comparator.comparing(Person::getWeight).reversed()));
		System.out.println("先按照年龄升序排列,再按照体重降序排列");
		persons.forEach(p -> System.out.println(p));
		//2:Predicate 复合lambda表达式
		Predicate<Person> ori = (p) -> p.getAge() > 5000;
		Predicate<Person> negate = ori.negate();
		System.out.println("年龄不大于5000:");
		persons.forEach(p -> {
			if(negate.test(p)) {
				System.out.println(p);
			}
		});
		Predicate<Person> and = ori.and((p) -> p.getWeight() > 2000);
		System.out.println("年龄大于5000且体重大于2000");
		persons.forEach(p -> {
			if(and.test(p)) {
				System.out.println(p);
			}
		});
		Predicate<Person> or = ori.or((p) -> p.getWeight() > 2000);
		System.out.println("年龄大于5000或体重大于2000");
		persons.forEach(p -> {
			if(or.test(p)) {
				System.out.println(p);
			}
		});
		//3:Function 复合lambda表达式
		Function<Integer, Integer> f1 = (p) -> p + 1;
		Function<Integer, Integer> f2 = (p) -> p * 3;
		//andThen是原始Function先执行
//	    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
//	        Objects.requireNonNull(after);
//	        return (T t) -> after.apply(apply(t));
//	    }
		Function<Integer, Integer> andThen = f1.andThen(f2).andThen(f2);
		//compose是传入的Function先执行
//		default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
//	        Objects.requireNonNull(before);
//	        return (V v) -> apply(before.apply(v));
//	    }
		Function<Integer, Integer> compose = f1.compose(f2).compose(f2);
		//1->2->6->18
		int a1 = andThen.apply(1);
		//1->3->9->10
		int a2 = compose.apply(1);
		System.out.println("试验Function复合函数");
		System.out.println(a1);
		System.out.println(a2);
	}
	
	/**
	 * 	流可以看做是集合遍历的高级迭代器.
	 * 	流支持以声明的方式处理集合数据.
	 * 	流支持并行处理集合数据.
	 * 	parallelStream就是并行处理.
	 * 
	 * 	parallelStream时候: <p>Person::getWeight打印线程名:<p>
	 * 	<ul>
	 * 		<li>线程名:ForkJoinPool.commonPool-worker-1</li>
	 * 		<li>线程名:ForkJoinPool.commonPool-worker-1</li>
	 * 		<li>线程名:ForkJoinPool.commonPool-worker-3</li>
	 * 	</ul>
	 * 	stream时候: <p>Person::getWeight打印线程名:<p>
	 * 	<ul>
	 * 		<li>线程名:main</li>
	 * 		<li>线程名:main</li>
	 * 		<li>线程名:main</li>
	 * 	</ul>
	 */
	public void streamUse() {
		List<Person> persons = new ArrayList<>();
		for (int i = 0; i < 100000; i++) {
			persons.add(createPerson());
		}
		List<Integer> ages = 
				persons.stream()
				//persons.parallelStream()
				.filter(p -> p.getAge() >= 4000)
				.sorted(Comparator.comparing(Person::getWeight)).map(Person::getAge).collect(Collectors.toList());
		ages.forEach(a -> System.out.println("年龄:" + a));
	}
	/**
	 * 
	 * 	流类似迭代器,只能遍历一次.重复遍历会报异常.
	Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
		at java.util.stream.AbstractPipeline.sourceStageSpliterator(Unknown Source)
		at java.util.stream.ReferencePipeline$Head.forEach(Unknown Source)
		at com.java8.T1.streamAndCollection(T1.java:526)
		at com.java8.T1.main(T1.java:33)
	 */
	public void streamAndCollection() {
		List<String> colors = Arrays.asList("赤","橙","黄","绿","青","蓝","紫");
		Stream<String> stream = colors.stream();
		stream.forEach(s -> System.out.println("颜色:" + s));
		stream.forEach(s -> System.out.println("颜色:" + s));
		//stream.map(s -> "颜色:"+s).forEach(System.out::println);
		//stream.map(s -> "颜色:"+s).forEach(System.out::println);
	}
	
	private List<Person> gainPersons(int count) {
		List<Person> persons = new ArrayList<>();
		for (int i = 0; i < count; i++) {
			persons.add(createPerson());
		}
		return persons;
	}
	public void streamAndOpt() {
		List<Person> persons = gainPersons(20);
		List<Integer> ages = persons.stream()
			.filter(p -> p.getAge() >= 4000)
			.limit(7)
			.map(Person::getAge)
			.collect(Collectors.toList());
		ages.forEach(System.out::println);
	}
	/**
	2
	4
	4
	6
	0
	8
	0
	distinct去重
	2
	4
	6
	0
	8
	 */
	public void streamDistinct() {
		List<Integer> numbers = Arrays.asList(1,2,1,3,4,5,4,5,6,0,8,0);
		numbers.stream().filter(n -> n%2==0)
		.forEach(System.out::println);
		System.out.println("distinct去重");
		numbers.stream().filter(n -> n%2==0)
		.distinct()
		.forEach(System.out::println);
	}
	/**
	1
	2
	3
	4
	5
	6
	7
	8
	skip跳过
	4
	5
	6
	7
	8
	 */
	public void streamSkip() {
		List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8);
		numbers.stream()
		.forEach(System.out::println);
		System.out.println("skip跳过");
		numbers.stream()
		.skip(3)
		.forEach(System.out::println);
	}
	/**
	 * flatMap很有意思
	 * <p>
	 * flatMap将流中的每一个元素转换为1个单独的流,然后将这些流合并为1个流.
	 * <p>
	 * 
	 *	 遍历c1<p>
		WhosWhosParty?Party?<p>
		遍历c2<p>
		WhosWhosParty?Party?<p>
		遍历c3<p>
		WhosParty?
	 */
	public void streamFlatMap() {
		List<String> strs = Arrays.asList("WhosWhos","Party?Party?");
		List<String[]> c1 = strs.stream().map(t -> t.split("")).distinct().collect(Collectors.toList());
		List<Stream<String>> c2 = strs.stream().map(t -> t.split("")).map(Arrays::stream).distinct().collect(Collectors.toList());
		List<String> c3 = strs.stream().map(t -> t.split("")).flatMap(Arrays::stream).distinct().collect(Collectors.toList());
		System.out.println("\n遍历c1");
		c1.forEach(c -> Arrays.asList(c).forEach(System.out::print));
		System.out.println("\n遍历c2");
		c2.forEach(c -> c.forEach(System.out::print));
		System.out.println("\n遍历c3");
		c3.forEach(System.out::print);
	}

	/**
	原始集合:<p>
	Person [age=599, weight=5172]	<p>	
	Person [age=7758, weight=8692]	<p>
	Person [age=5008, weight=4027]	<p>
	Person [age=3666, weight=2649]	<p>
	Person [age=530, weight=6640]	<p>
	Person [age=9725, weight=1172]	<p>
	Person [age=668, weight=9638]	<p>
	Person [age=972, weight=2023]	<p>
	Person [age=5729, weight=7016]	<p>
	Person [age=303, weight=8721]	<p>
	有人体重>=9999:false ; 所有人体重>=1000:true ; 没有人体重>=9999:true
	 */
	public void streamMatch() {
		List<Person> persons = gainPersons(10);
		System.out.println("原始集合:");
		persons.forEach(p -> System.out.println(p + "\t"));
		boolean m1 = persons.stream().anyMatch(p -> p.getWeight() >= 9999);
		boolean m2 = persons.stream().allMatch(p -> p.getWeight() >= 1000);
		boolean m3 = persons.stream().noneMatch(p -> p.getWeight() >= 9999);
		System.out.println("有人体重>=9999:" + m1 + " ; 所有人体重>=1000:" + m2 + " ; 没有人体重>=9999:" + m3);
	}
	/**
	 * 	试验下来,findAny 和 findFirst获取到的是同一个元素.<p>
	 * 
	原始集合:<p>
	Person [age=6826, weight=5618]	<p>
	Person [age=4771, weight=167]	<p>
	Person [age=3092, weight=1398]	<p>
	Person [age=6159, weight=2280]	<p>
	Person [age=4963, weight=6724]	<p>
	Person [age=613, weight=6299]	<p>
	Person [age=9483, weight=4837]	<p>
	Person [age=1164, weight=1892]	<p>
	Person [age=3014, weight=6467]	<p>
	Person [age=9969, weight=7290]	<p>
	任意1个体重>=5000的人:Person [age=6826, weight=5618] ; 第一个体重>=5000的人:Person [age=6826, weight=5618]
	 */
	public void streamFind() {
		List<Person> persons = gainPersons(10);
		System.out.println("原始集合:");
		persons.forEach(p -> System.out.println(p + "\t"));
		Person p1 = persons.stream().filter(p -> p.getWeight() >= 5000).findAny().get();
		Person p2 = persons.stream().filter(p -> p.getWeight() >= 5000).findFirst().get();
		System.out.println("任意1个体重>=5000的人:" + p1 + " ; 第一个体重>=5000的人:" + p2);
	}
	/**
	reduce接收2个参数,也可接收1个参数<p>;
	reduce接收2个参数,1个是初始值,1个是将流中的每个元素进行结合的逻辑;<p>
	源码说明:{@link Stream#reduce(Object, java.util.function.BinaryOperator)}}
	<pre>{@code
T result = identity;
for (T element : this stream)
	result = accumulator.apply(result, element)
return result;
	}
	</pre>
	reduce接收1个参数,初始值就是流中的第一个元素,然后将流中的每个元素进行结合<p>
	源码说明:{@link Stream#reduce(java.util.function.BinaryOperator)}}
	<pre>{@code
boolean foundAny = false;
T result = null;
for (T element : this stream) {
	if (!foundAny) {
		foundAny = true;
		result = element;
	}
	else
		result = accumulator.apply(result, element);
}
return foundAny ? Optional.of(result) : Optional.empty();
}
	</pre>
	 */
	public void streamReduce() {
		List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
		// 元素求和
		Integer n1 = nums.stream().reduce(0, (a, b) -> a + b);
		Integer n2 = nums.stream().reduce(0, Integer::sum);
		Integer n3 = nums.stream().reduce(Integer::sum).get();
		System.out.println("元素求和. n1:" + n1 + " ; n2:" + n2 + " ; n3:" + n3);
		// 求最大值
		Integer n4 = nums.stream().reduce(0, (a, b) -> Math.max(a, b));
		Integer n5 = nums.stream().reduce(0, Integer::max);
		Integer n6 = nums.stream().reduce(Integer::max).get();
		System.out.println("元素最大值. n4:" + n4 + " ; n5:" + n5 + " ; n6:" + n6);
		// 求最小值
		Integer n7 = nums.stream().reduce(Integer.MAX_VALUE, (a, b) -> Math.min(a, b));
		Integer n8 = nums.stream().reduce(Integer.MAX_VALUE, Integer::min);
		Integer n9 = nums.stream().reduce(Integer::min).get();
		System.out.println("元素最小值.n7:" + n7 + " ; n8:" + n8 + " ; n9:" + n9);
	}
	
	/**
	 * <pre>
狼牙月 伊人憔悴
我举杯 饮尽了风雪
事谁打翻尘世柜
惹尘埃是非
缘字诀 几番轮回
铜镜映无邪扎马尾
你若撒野晋升我把酒奉陪
	 * </pre>
	 */
	public void streamCreate() {
		//使用文件创建Stream
		try {
			Stream<String> strs = Files.lines(Paths.get("files.txt"),StandardCharsets.UTF_8);
			strs.forEach(System.out::println);
			strs.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		//使用数组创建Stream
		Stream.of(1,2,3);
		//创建空Stream
		Stream.empty();
		//generate可以创建无限流
		Stream.generate(() -> Math.random())
		.limit(20)
		.forEach(System.out::println);
		//iterate可以创建无限流
		//iterate类似reduce传入的两个参数
		Stream.iterate(100, (p) -> p+10)
		.limit(20)
		.forEach(System.out::println);
		//使用数值范围创建Stream
		IntStream.rangeClosed(1, 20)
		.forEach(System.out::println);
	}
	/**
	 * 
当前年龄:100
Person [age=100, weight=100]
Person [age=100, weight=100]
当前年龄:101
Person [age=101, weight=100]
Person [age=101, weight=100]
当前年龄:102
Person [age=102, weight=100]
Person [age=102, weight=100]
当前年龄:103
Person [age=103, weight=100]
Person [age=103, weight=100]
集合中元素数量:8
年龄最大Person:Person [age=103, weight=100]
年龄最小Persion:Person [age=100, weight=100]
年龄总和:812
年龄均值:101.5
每个Person年龄:before 100-101-102-103-100-101-102-103 after
每个年龄对应的人数:
100=2
101=2
102=2
103=2
先按年龄分组,再按体重分组:
{100={large=[Person [age=100, weight=100], Person [age=100, weight=100]]}, 101={large=[Person [age=101, weight=100], Person [age=101, weight=100]]}, 102={large=[Person [age=102, weight=100], Person [age=102, weight=100]]}, 103={large=[Person [age=103, weight=100], Person [age=103, weight=100]]}}
找出每个年龄最重的Person:
{100=Person [age=100, weight=100], 101=Person [age=101, weight=100], 102=Person [age=102, weight=100], 103=Person [age=103, weight=100]}
	 * 
	 */
	private void StreamCollectors() {
		List<Person> persons = Arrays.asList(new Person(100, 100), new Person(101, 100), new Person(102, 100),
				new Person(103, 100), new Person(100, 100), new Person(101, 100), new Person(102, 100),
				new Person(103, 100));
		Map<Integer, List<Person>> map = persons.stream().collect(Collectors.groupingBy(Person::getAge));
		for (Entry<Integer, List<Person>> entry : map.entrySet()) {
			System.out.println("当前年龄:" + entry.getKey());
			entry.getValue().forEach(System.out::println);
		}
		long count = persons.stream().count();
		System.out.println("集合中元素数量:" + count);
		Person max = persons.stream().collect(Collectors.maxBy(Comparator.comparing(Person::getAge))).get();
		System.out.println("年龄最大Person:" + max);
		Person min = persons.stream().collect(Collectors.minBy(Comparator.comparing(Person::getAge))).get();
		System.out.println("年龄最小Persion:" + min);
		int sum = persons.stream().collect(Collectors.summingInt(Person::getAge));
		System.out.println("年龄总和:" + sum);
		Double avg = persons.stream().collect(Collectors.averagingInt(Person::getAge));
		System.out.println("年龄均值:" + avg);
		String ages = persons.stream().map(Person::getAge).map(i -> ""+i).collect(Collectors.joining("-", "before ", " after"));
		System.out.println("每个Person年龄:" + ages);
		Map<Integer, Long> ageCount = persons.stream().collect(Collectors.groupingBy(Person::getAge, Collectors.counting()));
		System.out.println("每个年龄对应的人数:");
		for(Entry<Integer, Long> entry:ageCount.entrySet()) {
			System.out.println(entry);
		}
		System.out.println("先按年龄分组,再按体重分组:");
		Map<Integer, Map<String, List<Person>>> ageWeight = persons.stream().collect(Collectors.groupingBy(Person::getAge, Collectors.groupingBy(p -> {
			if(((Person) p).getAge() >= 100) {
				return "large";
			}else {
				return "small";
			}
		})));
		System.out.println(ageWeight);
		System.out.println("找出每个年龄最重的Person:");
		Map<Integer, Person> ageMaxWeight = persons.stream().collect(
				Collectors.groupingBy(Person::getAge, 
				Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparing(Person::getWeight)), Optional::get)));
		System.out.println(ageMaxWeight);
	}
	/**
游戏价格:100.0
Exception in thread "main" java.util.NoSuchElementException: No value present
	at java.util.Optional.get(Unknown Source)
	at com.java8.T1.OptionalUse(T1.java:860)
	at com.java8.T1.main(T1.java:56)
	 */
	public void OptionalUse() {
		double gamePrice = Optional.ofNullable(new PC()).map(PC::getGame).map(Game::getPrice).orElse(100.00D);
		System.out.println("游戏价格:" + gamePrice);
		System.out.println("试验空Optionnal.get : "+Optional.ofNullable(null).get());
	}
}