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 );
		 
		 
	}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.
  • 194.
  • 195.
  • 196.
  • 197.
  • 198.
  • 199.
  • 200.
  • 201.
  • 202.
  • 203.
  • 204.
  • 205.
  • 206.
  • 207.
  • 208.
  • 209.
  • 210.
  • 211.
  • 212.
  • 213.
  • 214.
  • 215.
  • 216.
  • 217.
  • 218.
  • 219.
  • 220.
  • 221.
  • 222.
  • 223.
  • 224.
  • 225.
  • 226.
  • 227.
  • 228.
  • 229.
  • 230.
  • 231.
  • 232.
  • 233.
  • 234.
  • 235.
  • 236.
  • 237.
  • 238.
  • 239.
  • 240.
  • 241.
  • 242.
  • 243.
  • 244.
  • 245.
  • 246.
  • 247.
  • 248.
  • 249.
  • 250.
  • 251.
  • 252.
  • 253.
  • 254.
  • 255.
  • 256.
  • 257.
  • 258.
  • 259.
  • 260.
  • 261.
  • 262.
  • 263.
  • 264.
  • 265.
  • 266.
  • 267.
  • 268.
  • 269.
  • 270.
  • 271.
  • 272.
  • 273.
  • 274.
  • 275.
  • 276.
  • 277.
  • 278.
  • 279.
  • 280.
  • 281.
  • 282.
  • 283.
  • 284.
  • 285.
  • 286.
  • 287.
  • 288.
  • 289.
  • 290.
  • 291.
  • 292.
  • 293.
  • 294.
  • 295.
  • 296.