一、函数式接口
1.1函数式接口概述
概念 有且仅有一个抽象方法的接口如何检测一个接口是不是函数式接口 @FunctionalInterface 放在接口定义的上方:如果接口是函数式接口,编译通过;如果不是,编译失败注意事项 我们自己定义函数式接口的时候,@FunctionalInterface是可选的,就算我不写这个注解,只要保证满足函数式接口定义的条件,也照样是函数式接口。但是,建议加上该注解
1.2函数式接口作为方法的参数
需求描述
定义一个类(RunnableDemo),在类中提供两个方法 一个方法是:startThread(Runnable r)方法参数Runnable是一个函数式接口 一个方法是主方法,在主方法中调用startThread方法 代码演示
public class RunnableDemo {
public static void main ( String[ ] args) {
startThread ( new Runnable ( ) {
@Override
public void run ( ) {
System. out. println ( Thread. currentThread ( ) . getName ( ) + "线程启动了" ) ;
}
} ) ;
startThread ( ( ) - > System. out. println ( Thread. currentThread ( ) . getName ( ) + "线程启动了" ) ) ;
}
private static void startThread ( Runnable r) {
new Thread ( r) . start ( ) ;
}
}
1.3函数式接口作为方法的返回值【应用】
需求描述
定义一个类(ComparatorDemo),在类中提供两个方法 一个方法是:ComparatorgetComparator()方法返回值Comparator是一个函数式接口 一个方法是主方法,在主方法中调用getComparator方法 代码演示
public class ComparatorDemo {
public static void main ( String[ ] args) {
ArrayList< String> array = new ArrayList < String> ( ) ;
array. add ( "cccc" ) ;
array. add ( "aa" ) ;
array. add ( "b" ) ;
array. add ( "ddd" ) ;
System. out. println ( "排序前:" + array) ;
Collections. sort ( array, getComparator ( ) ) ;
System. out. println ( "排序后:" + array) ;
}
private static Comparator< String> getComparator ( ) {
return ( s1, s2) - > s1. length ( ) - s2. length ( ) ;
}
}
1.4常用函数式接口之Supplier【应用】
Supplier接口 Supplier接口也被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据供我们使用。 常用方法 只有一个无参的方法 代码演示
public class SupplierDemo {
public static void main ( String[ ] args) {
String s = getString ( ( ) - > "林青霞" ) ;
System. out. println ( s) ;
Integer i = getInteger ( ( ) - > 30 ) ;
System. out. println ( i) ;
}
private static Integer getInteger ( Supplier< Integer> sup) {
return sup. get ( ) ;
}
private static String getString ( Supplier< String> sup) {
return sup. get ( ) ;
}
}
1.5Supplier接口练习之获取最大值【应用】
案例需求
定义一个类(SupplierTest),在类中提供两个方法 一个方法是:int getMax(Suppliersup)用于返回一个int数组中的最大值 一个方法是主方法,在主方法中调用getMax方法 示例代码
public class SupplierTest {
public static void main ( String[ ] args) {
int [ ] arr= { 19 , 50 , 28 , 37 , 46 } ;
int maxValue = getMax ( ( ) - > {
int max = arr[ 0 ] ;
for ( int i= 1 ; i< arr. length; i++ ) {
if ( arr[ i] > max) {
max= arr[ i] ;
}
}
return max;
} ) ;
System. out. println ( maxValue) ;
}
private static int getMax ( Supplier< Integer> sup) {
return sup. get ( ) ;
}
}
1.6常用函数式接口之Consumer【应用】
Consumer接口 Consumer接口也被称为消费型接口,它消费的数据的数据类型由泛型指定 常用方法 Consumer:包含两个方法 代码演示
public class ConsumerDemo {
public static void main ( String[ ] args) {
operatorString ( "林青霞" , s- > System. out. println ( s) ) ;
operatorString ( "林青霞" , s- > System. out. println ( new StringBuilder ( s) . reverse ( ) . toString ( ) ) ) ;
System. out. println ( "--------" ) ;
operatorString ( "林青霞" , s- > System. out. println ( s) , s- > System. out. println ( new StringBuilder ( s) . reverse ( ) . toString ( ) ) ) ;
}
private static void operatorString ( String name, Consumer< String> con1,
Consumer< String> con2) {
con1. andThen ( con2) . accept ( name) ;
}
private static void operatorString ( String name, Consumer< String> con) {
con. accept ( name) ;
}
}
1.7Consumer接口练习之按要求打印信息【应用】
案例需求
String[] strArray = {“林青霞,30”, “张曼玉,35”, “王祖贤,33”}; 字符串数组中有多条信息,请按照格式:“姓名:XX,年龄:XX"的格式将信息打印出来 要求:
把打印姓名的动作作为第一个Consumer接口的Lambda实例 把打印年龄的动作作为第二个Consumer接口的Lambda实例 将两个Consumer接口按照顺序组合到一起使用 示例代码
public class ConsumerTest {
public static void main ( String[ ] args) {
String[ ] strArray = { "林青霞,30" , "张曼玉,35" , "王祖贤,33" } ;
printInfo ( strArray, str- > System. out. print ( "姓名:" + str. split ( "," ) [ 0 ] ) , str- > System. out. println ( ",年龄:" +
Integer. parseInt ( str. split ( "," ) [ 1 ] ) ) ) ;
}
private static void printInfo ( String[ ] strArray, Consumer< String> con1,
Consumer< String> con2) {
for ( String str: strArray) {
con1. andThen ( con2) . accept ( str) ;
}
}
}
1.8常用函数式接口之Predicate【应用】
Predicate接口 Predicate接口通常用于判断参数是否满足指定的条件 常用方法 代码演示
public class PredicateDemo01 {
public static void main ( String[ ] args) {
boolean b1 = checkString ( "hello" , s- > s. length ( ) > 8 ) ;
System. out. println ( b1) ;
boolean b2 = checkString ( "helloworld" , s- > s. length ( ) > 8 ) ;
System. out. println ( b2) ;
}
private static boolean checkString ( Strings, Predicate< String> pre) {
return pre. negate ( ) . test ( s) ;
}
}
public class PredicateDemo02 {
public static void main ( String[ ] args) {
boolean b1 = checkString ( "hello" , s- > s. length ( ) > 8 ) ;
System. out. println ( b1) ;
boolean b2 = checkString ( "helloworld" , s- > s. length ( ) > 8 ) ;
System. out. println ( b2) ;
boolean b3 = checkString ( "hello" , s- > s. length ( ) > 8 , s- > s. length ( ) < 15 ) ;
System. out. println ( b3) ;
boolean b4 = checkString ( "helloworld" , s- > s. length ( ) > 8 , s- > s. length ( ) < 15 ) ;
System. out. println ( b4) ;
}
private static boolean checkString ( Strings, Predicate< String> pre1,
Predicate< String> pre2) {
return pre1. or ( pre2) . test ( s) ;
}
private static boolean checkString ( Strings, Predicate< String> pre) {
return pre. test ( s) ;
}
}
1.9Predicate接口练习之筛选满足条件数据【应用】
练习描述
String[] strArray = {“林青霞,30”, “柳岩,34”, “张曼玉,35”, “貂蝉,31”, “王祖贤,33”}; 字符串数组中有多条信息,请通过Predicate接口的拼装将符合要求的字符串筛选到集合ArrayList中,并遍历ArrayList集合 同时满足如下要求:姓名长度大于2;年龄大于33 分析
有两个判断条件,所以需要使用两个Predicate接口,对条件进行判断 必须同时满足两个条件,所以可以使用and方法连接两个判断条件 示例代码
public class PredicateTest {
public static void main ( String[ ] args) {
String[ ] strArray = { "林青霞,30" , "柳岩,34" , "张曼玉,35" , "貂蝉,31" , "王祖贤,33" } ;
ArrayList< String> array = myFilter ( strArray, s- > s. split ( "," ) [ 0 ] . length ( ) > 2 ,
s- > Integer. parseInt ( s. split ( "," ) [ 1 ] ) > 33 ) ;
for ( String str: array) {
System. out. println ( str) ;
}
}
private static ArrayList< String> myFilter ( String[ ] strArray, Predicate< String>
pre1, Predicate< String> pre2) {
ArrayList< String> array = new ArrayList < String> ( ) ;
for ( Strings tr: strArray) {
if ( pre1. and ( pre2) . test ( str) ) {
array. add ( str) ;
}
}
return array;
}
}
1.10常用函数式接口之Function【应用】
Function接口 Function<T,R>接口通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值 常用方法 代码演示
public class FunctionDemo {
public static void main ( String[ ] args) {
convert ( "100" , s- > Integer. parseInt ( s) ) ;
convert ( 100 , i- > String. valueOf ( i+ 566 ) ) ;
convert ( "100" , s- > Integer. parseInt ( s) , i- > String. valueOf ( i+ 566 ) ) ;
}
private static void convert ( String s, Function< String, Integer> fun) {
int i = fun. apply ( s) ;
System. out. println ( i) ;
}
private static void convert ( int i, Function< Integer, String> fun) {
String s= fun. apply ( i) ;
System. out. println ( s) ;
}
private static void convert ( String s, Function< String, Integer> fun1,
Function< Integer, String> fun2) {
String ss = fun1. andThen ( fun2) . apply ( s) ;
System. out. println ( ss) ;
}
}
1.11Function接口练习之按照指定要求操作数据【应用】
练习描述
String s = “林青霞,30”; 请按照我指定的要求进行操作: 1:将字符串截取得到数字年龄部分 2:将上一步的年龄字符串转换成为int类型的数据 3:将上一步的int数据加70,得到一个int结果,在控制台输出请通过Function接口来实现函数拼接 示例代码
public class FunctionTest {
public static void main ( String[ ] args) {
String s = "林青霞,30" ;
convert ( s, ss- > ss. split ( "," ) [ 1 ] , Integer: : parseInt, i- > i+ 70 ) ;
}
private static void convert ( String s, Function< String, String> fun1, Function< String, Integer> fun2, Function< Integer, Integer> fun3) {
int i = fun1. andThen ( fun2) . andThen ( fun3) . apply ( s) ;
System. out. println ( i) ;
}
}
二.Strem流
2.1体验Stream流【理解】
案例需求 按照下面的要求完成集合的创建和遍历
创建一个集合,存储多个字符串元素 把集合中所有以"张"开头的元素存储到一个新的集合 把"张"开头的集合中的长度为3的元素存储到一个新的集合 遍历上一步得到的集合 原始方式示例代码
public class StreamDemo {
public static void main ( String[ ] args) {
ArrayList< String> list = new ArrayList < String> ( ) ;
list. add ( "林青霞" ) ;
list. add ( "张曼玉" ) ;
list. add ( "王祖贤" ) ;
list. add ( "柳岩" ) ;
list. add ( "张敏" ) ;
list. add ( "张无忌" ) ;
ArrayList< String> zhangList = new ArrayList < String> ( ) ;
for ( String s: list) {
if ( s. startsWith ( "张" ) ) {
zhangList. add ( s) ;
}
}
ArrayList< String> threeList = new ArrayList < String> ( ) ;
for ( String s: zhangList) {
if ( s. length ( ) == 3 ) {
threeList. add ( s) ;
}
}
for ( String s: threeList) {
System. out. println ( s) ;
}
System. out. println ( "--------" ) ;
list. stream ( ) . filter ( s- > s. startsWith ( "张" ) ) . filter ( s- > s. length ( ) == 3 ) . forEach ( System. out: : println) ;
}
}
public class StreamDemo {
public static void main ( String[ ] args) {
ArrayList< String> list = new ArrayList < String> ( ) ;
list. add ( "林青霞" ) ;
list. add ( "张曼玉" ) ;
list. add ( "王祖贤" ) ;
list. add ( "柳岩" ) ;
list. add ( "张敏" ) ;
list. add ( "张无忌" ) ;
list. stream ( ) . filter ( s- > s. startsWith ( "张" ) ) . filter ( s- > s. length ( ) == 3 ) . forEach ( System. out: : println) ;
}
}
Stream流的好处
直接阅读代码的字面意思即可完美展示无关逻辑方式的语义:获取流、过滤姓张、过滤长度为3、逐一打 印 Stream流把真正的函数式编程风格引入到Java中
2.2 Stream流的常见生成方式【应用】
Stream流的思想 生成Stream流的方式
Collection体系集合 使用默认方法stream()生成流,default Streamstream() Map体系集合 把Map转成Set集合,间接的生成流 数组 通过Stream接口的静态方法of(T… values)生成流 代码演示
public class StreamDemo {
public static void main ( String[ ] args) {
List< String> list = new ArrayList < String> ( ) ;
Stream< String> listStream = list. stream ( ) ;
Set< String> set = new HashSet < String> ( ) ;
Stream< String> setStream = set. stream ( ) ;
Map< String, Integer> map = new HashMap < String, Integer> ( ) ;
Stream< String> keyStream = map. keySet ( ) . stream ( ) ;
Stream< Integer> valueStream = map. values ( ) . stream ( ) ;
Stream< Map. Entry< String, Integer> > entryStream = map. entrySet ( ) . stream ( ) ;
String[ ] strArray = { "hello" , "world" , "java" } ;
Stream< String> strArrayStream = Stream. of ( strArray) ;
Stream< String> strArrayStream2 = Stream. of ( "hello" , "world" , "java" ) ;
Stream< Integer> intStream = Stream. of ( 10 , 20 , 30 ) ;
}
}
2.3Stream流中间操作方法【应用】
概念 中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作。 常见方法 filter代码演示
public class StreamDemo01 {
public static void main ( String[ ] args) {
ArrayList< String> list = new ArrayList < String> ( ) ;
list. add ( "林青霞" ) ;
list. add ( "张曼玉" ) ;
list. add ( "王祖贤" ) ;
list. add ( "柳岩" ) ;
list. add ( "张敏" ) ;
list. add ( "张无忌" ) ;
list. stream ( ) . filter ( s- > s. startsWith ( "张" ) ) . forEach ( System. out: : println) ;
System. out. println ( "--------" ) ;
list. stream ( ) . filter ( s- > s. length ( ) == 3 ) . forEach ( System. out: : println) ;
System. out. println ( "--------" ) ;
list. stream ( ) . filter ( s- > s. startsWith ( "张" ) ) . filter ( s- > s. length ( ) == 3 ) . forEach ( System. out: : println) ;
}
}
public class StreamDemo02 {
public static void main ( String[ ] args) {
ArrayList< String> list = new ArrayList < String> ( ) ;
list. add ( "林青霞" ) ;
list. add ( "张曼玉" ) ;
list. add ( "王祖贤" ) ;
list. add ( "柳岩" ) ;
list. add ( "张敏" ) ;
list. add ( "张无忌" ) ;
list. stream ( ) . limit ( 3 ) . forEach ( System. out: : println)
; System. out. println ( "--------" ) ;
list. stream ( ) . skip ( 3 ) . forEach ( System. out: : println) ;
System. out. println ( "--------" ) ;
list. stream ( ) . skip ( 2 ) . limit ( 2 ) . forEach ( System. out: : println) ;
}
}
public class StreamDemo03 {
public static void main ( String[ ] args) {
ArrayList< String> list = new ArrayList < String> ( ) ;
list. add ( "林青霞" ) ;
list. add ( "张曼玉" ) ;
list. add ( "王祖贤" ) ;
list. add ( "柳岩" ) ;
list. add ( "张敏" ) ;
list. add ( "张无忌" ) ;
Stream< String> s1= list. stream ( ) . limit ( 4 ) ;
Stream< String> s2= list. stream ( ) . skip ( 2 ) ;
Stream. concat ( s1, s2) . distinct ( ) . forEach ( System. out: : println) ;
}
}
public class StreamDemo04 {
public static void main ( String[ ] args) {
ArrayList< String> list= new ArrayList < String> ( ) ;
list. add ( "linqingxia" ) ;
list. add ( "zhangmanyu" ) ;
list. add ( "wangzuxian" ) ;
list. add ( "liuyan" ) ;
list. add ( "zhangmin" ) ;
list. add ( "zhangwuji" ) ;
list. stream ( ) . sorted ( ( s1, s2) - > {
int num= s1. length ( ) - s2. length ( ) ;
int num2= num== 0 ? s1. compareTo ( s2) : num;
return num2;
} ) . forEach ( System. out: : println) ;
}
}
public class StreamDemo05 {
public static void main ( String[ ] args) {
ArrayList< String> list= new ArrayList < String> ( ) ;
list. add ( "10" ) ;
list. add ( "20" ) ;
list. add ( "30" ) ;
list. add ( "40" ) ;
list. add ( "50" ) ;
int result= list. stream ( ) . mapToInt ( Integer: : parseInt) . sum ( ) ;
System. out. println ( result) ;
}
}
2.4Stream流终结操作方法【应用】
概念 终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作。 常见方法 代码演示
public class StreamDemo {
public static void main ( String[ ] args) {
ArrayList< String> list= new ArrayList < String> ( ) ;
list. add ( "林青霞" ) ;
list. add ( "张曼玉" ) ;
list. add ( "王祖贤" ) ;
list. add ( "柳岩" ) ;
list. add ( "张敏" ) ;
list. add ( "张无忌" ) ;
long count= list. stream ( ) . filter ( s- > s. startsWith ( "张" ) ) . count ( ) ;
System. out. println ( count) ;
}
}
2.5Stream流综合练习【应用】
案例需求 现在有两个ArrayList集合,分别存储6名男演员名称和6名女演员名称,要求完成如下的操作
男演员只要名字为3个字的前三人 女演员只要姓林的,并且不要第一个 把过滤后的男演员姓名和女演员姓名合并到一起 把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据 演员类Actor已经提供,里面有一个成员变量,一个带参构造方法,以及成员变量对应的get/set方法 代码实现
public class Actor {
private String name;
public Actor ( String name) {
this . name= name;
}
public String getName ( ) {
return name;
}
public void setName ( String name) {
this . name= name;
}
}
public class StreamTest {
public static void main ( String[ ] args) {
ArrayList< String> manList= new ArrayList < String> ( ) ;
manList. add ( "周润发" ) ;
manList. add ( "成龙" ) ;
manList. add ( "刘德华" ) ;
manList. add ( "吴京" ) ;
manList. add ( "周星驰" ) ;
manList. add ( "李连杰" ) ;
ArrayList< String> womanList = new ArrayList < String> ( ) ;
womanList. add ( "林心如" ) ;
womanList. add ( "张曼玉" ) ;
womanList. add ( "林青霞" ) ;
womanList. add ( "柳岩" ) ;
womanList. add ( "林志玲" ) ;
womanList. add ( "王祖贤" ) ;
Stream. concat ( manList. stream ( ) . filter ( s- > s. length ( ) == 3 ) . limit ( 3 ) ,
womanList. stream ( ) . filter ( s- > s. startsWith ( "林" ) ) . skip ( 1 ) ) . map ( Actor: : new ) .
forEach ( p- > System. out. println ( p. getName ( ) ) ) ;
}
}
2.6Stream流的收集操作【应用】
概念 对数据使用Stream流的方式操作完毕后,可以把流中的数据收集到集合中。 常用方法 工具类Collectors提供了具体的收集方式 代码演示
public class CollectDemo {
public static void main ( String[ ] args) {
List< String> list= new ArrayList < String> ( ) ;
list. add ( "林青霞" ) ;
list. add ( "张曼玉" ) ;
list. add ( "王祖贤" ) ;
list. add ( "柳岩" ) ;
Set< Integer> set = new HashSet < Integer> ( ) ;
set. add ( 10 ) ;
set. add ( 20 ) ;
set. add ( 30 ) ;
set. add ( 33 ) ;
set. add ( 35 ) ;
String[ ] strArray = { "林青霞,30" , "张曼玉,35" , "王祖贤,33" , "柳岩,25" } ;
Stream< String> arrayStream = Stream. of ( strArray) . filter ( s- >
Integer. parseInt ( s. split ( "," ) [ 1 ] ) > 28 ) ;
Map< String, Integer> map = arrayStream. collect ( Collectors. toMap ( s- >
s. split ( "," ) [ 0 ] , s- > Integer. parseInt ( s. split ( "," ) [ 1 ] ) ) ) ;
Set< String> keySet = map. keySet ( ) ;
for ( String key: keySet) {
Integervalue= map. get ( key) ;
System. out. println ( key+ "," + value) ;
}
}
}