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) 编辑 收藏 举报