FunctionalInterface我们把只定义了单个方法的接口称为FunctionalInterface,并用注解@FunctionalInterface来标记。比如Callable接口:@FunctionalInterfacepublicinterfaceCallable{Vcall()throwsException;}Lambda表达式可以用来支持函数式编程Lambda表达式当我们使用Arrays.sort()进行排序时,我们可以传入作为匿名类实现的Comparator实例:String[]array=...Arrays.sort(array,newComparator(){publicintcompare(Strings1,Strings2){returns1.compareTo(s2);}});但是这种写法相当繁琐,所以从JDK8开始,我们可以使用Lambda表达式来代替这种繁琐的写法:String[]array=...Arrays.sort(array,(s1,s2)->{returns1.compareTo(s2);});使用Lambda只需要写方法的定义,参数类型可以省略,编译器会自动推断String类型,->{...}表示方法体,如果只有一行返回代码,可以更简洁:Arrays.sort(array,(s1,s2)->s1.compareTo(s2));返回值的类型也是编译器自动推断出来的,这里推断的返回值是int,所以只要返回int,编译器就不会报错。除了使用Lambda,还可以直接传入方法引用:publicstaticvoidmain(String[]args){String[]array=newString[]{"Apple","Orange","Banana","Lemon"};Arrays.sort(数组,Main::cmp);System.out.println(String.join(",",array));}staticintcmp(Strings1,Strings2){returns1.compareTo(s2);}上面的代码是什么意思?可以看到Arrays.sort需要传入一个数组和Comparator接口。Comparator中有一个方法intcompare(To1,Too2)。我们定义的方法cmp与compare方法具有相同的方法签名,即方法参数和返回类型相同,则可以直接使用方法引用。让我们看另一个例子:publicstaticvoidmain(String[]args){String[]array=newString[]{"Apple","Orange","Banana","Lemon"};Arrays.sort(数组,String::compareTo);System.out.println(String.join(",",array));}查看String的compareTo方法,发现只有一个参数,但不是上面说的方法签名必须一致吗?这里发生了什么?因为前面的方法是静态方法,这里是实例方法。实例方法的第一个隐式参数总是在this中传递,相当于:publicstaticintcompareTo(this,Stringo);所以String::compareTo和compare方法签名是一致的Stream一个全新的churnAPI,可以存储有限或者无限的元素,Streamam是惰性计算,计算通常发生在结果获取的最后。因此,StreamAPI的基本用法是:创建一个Stream,然后进行多次转换,最后调用一个求值方法得到实际的计算结果:HowtocreateaStream?Stream.ofStreamstream=Stream.of(“ABCD”);数组或CollectionStreamstream=Arrays.stream(newString[]{"A","B","C"});Streamstream1=List.of("A","B","C").stream();Supplier需要通过Stream.generate()传入Supplier对象publicstaticStreamgenerate(Suppliers){Objects.requireNonNull(s);返回StreamSupport。stream(newStreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE,s),false);}Supplier是一个函数式接口,我们可以自己实现这个接口@FunctionalInterfacepublicinterfaceSupplier{/***得到一个结果.**@return结果*/Tget();}classNaturalSupplierimplementsSupplier{intn=0;@Override公共整数get(){返回n++;}}基于Supplier创建的Stream会不断调用get()生成下一个元素,可以用来表示无限序列publicstaticvoidmain(String[]args){Streamstream=Stream.生成(新的NatualSupplier());stream.limit(20).forEach(System.out::println);}因为会一直调用get(),所以我们要对基本类型设置一个限制stream.limit(20),因为Java的泛型不支持基本类型,并且只能使用Integer等包装类型,但是Stream会频繁的unbox和box,所以为了提高效率,Java标准库为我们提供了Stream的三种基本类型->IntStream,LongStream,DoubleStreammapStream.map()是一种转换方法,将一个Stream转换为另一个StreamStreamstream=List.of(1,2,3).stream();StreamstreamMap=stream.地图(项目->项目*项目);让我们看一下map(),它最终将返回一个Stream/***返回一个流,该流由将给定*函数应用于此流的元素的结果组成。**这是一个中间*操作。**@param新流的元素类型*@parammappera非干扰,*无状态*应用于每个元素的函数*@return新流*/Streammap(Functionmapper);Stream.map()传入函数式接口Function,apply()最终返回计算结果@FunctionalInterfacepublicinterfaceFunction{/***Applysthisfunctiontothegivenargument.**@paramtthefunctionargument*@returnthefunctionresult*/Rapply(Tt);...}filterStream.filter()是另一种常用的Stream转换方法filter是将不满足条件的元素过滤掉,形成一个新的StreamStreamstream=List.of(3,4,6).stream();StreamstreamMap=stream.filter(item->item%2==0);filter接收Predicate,test()过滤掉不满足条件的元素@FunctionalInterfacepublicinterfacePredicate{/***Evaluatesthispredicateonthegivenargument.**@param吨输入参数*@return{@codetrue}如果输入参数与谓词匹配,*否则{@codefalse}*/booleantest(Tt);}reduce是Stream的一种聚合方法,它获取a的所有元素Stream根据聚合函数聚合成一个结果Streamstream=List.of(3,4,6).stream();Integerreduce=stream.reduce(0,(acc,n)->acc+n);Stream.reduce()接收BinaryOperator,它继承自BiFunction。在BiFunction中,有Rapply(Tt,Uu)/***将此函数应用于给定的参数。**@paramt第一个函数参数*@paramu第二个函数参数*@return函数结果*/Rapply(Tt,Uu);所以BinaryOperator其实是重写了父接口的apply()方法,通过这个方法累加计算第一个参数0相当于初值,看源码注释:*{@code*Tresult=identity;*for(Telement:thisstream)*result=accumulator.apply(result,element)*returnresult;*}}}}Stream,reduce会立即得到结果。如何保存经过转换操作的元素?输出是一个集合:collect()并传入Collectors.toList()对象:Streamstream=List.of(3,4,6).stream();Listlist=stream.map(n->n*n).collect(Collectors.toList());作为数组输出:Streamstream=List.of("Apple","Banana","Pear").stream();String[]array=stream.toArray(String[]::new);输出为Map:Streamstream=List.of("Apple:Banana","Pear:Peach").stream();Mapmap=stream.collect(Collectors.toMap(//mapped键s->s.substring(0,s.indexOf(':')),//映射到值s->s.substring(s.indexOf(':')+1)));组输出:Streamstream=List.of("Apple","Banana","Blackberry","Coconut","Avocado","Cherry","Apricots").stream();Map>groups=stream.collect(Collectors.groupingBy(s->s.substring(0,1),Collectors.toList()));上面代码中的收集器。groupingBy根据元素的首字母进行分组