JDK8 新特性 lamdda表达式 Stream 接口支持实例方法

JDK 8最大的特点在于lamdda 表达式和Stream 集合处理工具流

 

 

	/**
	 * lamdda 表达式的写法
	 */
	@Test
	public void test1(){
		//传统写法,匿名内部类
		Function<String,String> funOld = new Function<String, String>() {
			@Override
			public String apply(String t) {
				return t;
			}
		};
		
		
		//lamdda表达式完整写法
		Function<String,String> funAll = (String item)-> {
			return item;
		};
		
		//参数类型可以省略,因为可以通过泛型推断得出
		Function<String,String> fun1 = (item)-> {
			return item;
		};
		
		//只有一个参数的时候参数扩号可以省略
		Function<String,String> fun2 = item-> {
			return item;
		};
		
		//只有一行代码并且,那么这个行代码的值就是返回值,return和大括号也可以剩余
		Function<String,String> fun3 = item->item;
		
		//使用类名或者对象名::方法名字,可以得到对应方法的引用。
		Consumer<String> c = System.out::println;
		
		
		//lamdda 表达式可以看做是 一接口函数的实现。 每一个方法都可以被指定规则的接口函数指向使用 类::实例方法的时候,需要接口函数的第一个参数就是这个 类的实例对象。
		//接口函数,有且只有一个抽象方法的接口,这个方法不能是 defualt 和 static的
	}


	/**
	 * 最基础的函数接口 和以前常用的一些方法对应关系
	 * 
	 * 类::实例方法 格式的 lamdda 表达式  等价于 a(类,返回值) 接口函数
	 */
	@Test
	public void test2(){
		Goods goods = Goods.randomGoods();
		
		//很多已经存在的方法可以指向对应参数的接口函数,下面三种最基础的函数接口
		
		//Consumer 接口函数,只有一个参数没有返回值
		Consumer<String> sysout = System.out::println;
		sysout.accept("哇哈哈哈哈");
		
		//Supplier接口函数,只有返回值
		Supplier<String> supplier1 = goods::getData;
		
		
		//Function接口函数,一个参数一个返回值
		Function<Double,Long> fun = Math::round;
		
		List<Goods> list = new ArrayList<>();
		//Predicate,有一个参数,返回是否,是 function的 特殊情况
		Predicate<Goods> predicate = list::contains;
		
		
		//2个参数的Function
		BiFunction<Integer,Integer,Integer> bif = (Integer a,Integer b)->{
			return a+b;
		};

		//实例::实例方法 指向实例方法
		Supplier<Long> supplier =  goods::getId;
		System.out.println(supplier.get());
		

		//类::类方法  等于   a(参数,返回值)
		Supplier<Double> f2 =  Math::random;
		System.out.println( f2.get() );


		//类::实例方法 格式的 lamdda 表达式  等价于 a(类,返回值) 接口函数(接口函数或者lamdda表达式的第一个参数是类实例)
		Function<Goods,Long> f = Goods::getId;
		Function<Goods,Long> ff = item->item.getId();
		f.apply(  Goods.randomGoods() );
		ff.apply(  Goods.randomGoods() );
		

		// Comparable.compareTo 接口函数 的实例可以指向 Comparator
		Comparator<String> comparator = String::compareTo;
		
	}


	/**
	 * 使用函数接口调用被 lamdda 表达式包裹的对象 get,set 方法
	 *
	 * @param
	 * @return: void
	 * @Author: ZHANGYUKUN
	 * @Date: 2022/6/13
	 */
	@Test
	public void test3(){

		//使用 lamdda 表达式 在一个对象get方法上包一层
		Function<Goods,Long> function = p->{
			return p.getId();
		};
		System.out.println( function.apply(Goods.randomGoods()) );


		//使用 lamdda 表达式 在 set 方法上包一层
		BiConsumer<Goods,Long>	biConsumer = (p1,p2)->{
			 p1.setId( p2 );
		};

		Goods goods = Goods.randomGoods();
		biConsumer.accept( goods,1L );
		System.out.println( goods.getId() );


	}


	/**
	 * 构造器引用
	 *
	 * @param
	 * @return: void
	 * @Author: ZHANGYUKUN
	 * @Date: 2022/6/13
	 */
	@Test
	public void test4(){
		//使用无参构造器
		Supplier<Goods> consumer = Goods::new;
		System.out.println(JSONObject.toJSONString( consumer.get()));


		//使用有参数的构造器
		Function<String,Goods> consumer2 = Goods::new;
		System.out.println(JSONObject.toJSONString( consumer2.apply("aaaaa") ));
		

		//数组引用
		Function<Integer,String[]> consumer3 = String[]::new;
		System.out.println(JSONObject.toJSONString( consumer3.apply(10 ) ));
		

		//集合引用
		Supplier<List<String>> supplier4 = ArrayList<String>::new;
		Function<Integer,List<String>> function5 = ArrayList<String>::new;
		

		//String[] a = new String[]{"1","2","3"};
		//String[] b = new String[10];

	}





	/**
	 * stram 无限流,按照指定规则,无限生成元素,然后无限循环
	 *
	 */
	@Test
	public void stram2(){
		//Stream
		Stream.iterate( 0, item->++item ).limit(100).forEach( System.out::println );

		Stream.generate( ()-> Goods.randomGoods() ).limit(100).forEach( System.out::println );
	}


	/**
	 * stram 流的常见用法
	 *
	 */
	@Test
	public void stram3(){
		Goods[] array = new Goods[3];
		array[0] = Goods.randomGoods();
		array[1] = Goods.randomGoods();
		array[2] = Goods.randomGoods();
		List<String> data = Arrays.asList("1","2","9","0");
		List<String> dataNull = Arrays.asList();
		
		
		
		

		List<Goods> list = new ArrayList<>();

		//流生产集合
		list = list.stream().collect(Collectors.toList()  );


		//数组转集合
		list = Arrays.stream(array).collect(Collectors.toList());

		//遍历
		Stream.of( array ).forEach( System.out::println );
		System.out.println( JSONObject.toJSONString( list ) );

		
		//排序(实现Comparable的可以直接排序,升序)
		System.out.println("自带排序:" + Stream.of( 1,3,9,5 ).sorted().collect( Collectors.toList() )  );
		
		//没实现Comparable的元素的集合可以通过传入Comparator实现排序,下面通过ID排序
		List<Goods> list2 = Stream.of( array ).sorted(new Comparator<Goods>() {
			@Override
			public int compare(Goods o1, Goods o2) {
				return (int)(o1.getId()-o2.getId());
			}
		}).collect( Collectors.toList() );
		System.out.println("指定排序:" + JSONObject.toJSONString( list2 )  );
		
		
		//toArray,感觉没什么卵用,类型也错还会报错,保证类型正确的情况下可以把集合转换成数组 
		String[] ar =  data.stream().toArray( item-> {
			 return new String[item];
		 }  );
		System.out.println( "数组:" +ar.length );
		
		
		 
		//peek 不会终止流的遍历(而且是是用的元素前调用的,调试很好用)
		data.stream().peek(System.out::println).forEach(System.out::println);
		
		
		List<List<Goods>> list22 = new ArrayList<>();
		list22.add(  Arrays.asList( Goods.randomGoods(),Goods.randomGoods() ) );
		list22.add(  Arrays.asList( Goods.randomGoods(),Goods.randomGoods() ) );
		list22.add(  Arrays.asList( Goods.randomGoods(),Goods.randomGoods() ) );
		
		
		//flatMap把多维度的集合展开成一维集合,例子是把二维集合,展开然后ID求和
		Optional<Long>  sum = list22.stream().flatMap( item->item.stream() ).map(Goods::getId).reduce( Math::addExact );
		System.out.println("求和:" +  sum.orElse(-1L) );
		
		
		//reduce,可以理解成把一个集合的数据合并起来(mapreduce 的 合并类似)
		Optional<String>  op = data.stream().reduce( (a,b)->a+b );
		System.out.println( op.get() );
		
		
		//Optional 可以减少空指针的辅助类
		Optional<String>  op2 = dataNull.stream().reduce( (a,b)->a+b );
		
		//取到到就给默认值
		System.out.println( op2.orElseGet( ()->"1" ) );
		//System.out.println( op2.orElseThrow(()-> new RuntimeException("为空则抛出") ) );
		
		Optional.of("只能包装非空对象");
		Optional.ofNullable(null);
		
		
			
		//toCollection(把结果装换成任意集合)
		List<String> aaa =  dataNull.stream().collect( Collectors.toCollection(()->new LinkedList<String>())  );
		System.out.println( "toCollection:" + aaa.getClass() );
		

		
		//summarize(汇总,然后可以知己去平均值,最大最小值,数量等等)
		DoubleSummaryStatistics doubleSummaryStatistics  = dataNull.stream().collect( Collectors.summarizingDouble( item->Double.valueOf(item) ) );
		System.out.println( doubleSummaryStatistics.getMax() );
		System.out.println( doubleSummaryStatistics.getMin() );
		System.out.println( doubleSummaryStatistics.getAverage() );
		 
		 
		 

		//分组(分组的第一个值是分组键,第二个是包装组的容器,第三个是元素集合)
	 	Map<Long,Set<Goods>> map =    list2.stream().collect( Collectors.groupingBy( Goods::getId ,LinkedHashMap::new, Collectors.toSet() ) );
		System.out.println( map.getClass() );
		
		
		//分区(相当于只有两个组的分组)
		Map<Boolean, List<Goods>> pt  =  list2.stream().collect( Collectors.partitioningBy((item->true))  );
		System.out.println(  pt.get(true).size() );
		System.out.println(  pt.get(false).size() );
		
		

		//collectingAndThen(先生产集合,然后处理一下),比如分组然后取到所有分组key
		Set<Long> keySet =  list2.stream().collect( Collectors.collectingAndThen(Collectors.groupingBy( Goods::getId ,LinkedHashMap::new, Collectors.toSet() ), item->item.keySet() )  );
		System.out.println(  keySet );
		 
		 
	}
  

  

posted on 2022-06-15 23:09  zhangyukun  阅读(69)  评论(0编辑  收藏  举报

导航