JDK8开始支持Lambda表达式,用来让程序编写更优雅。
利用Lambda可以更简洁的实现匿名内部类与函数声明与调用。
基于Lambda提供stream流式处理极大简化对集合的操作。
//四则运算接口
public interface MathOperation{
public Float operate(Integer a, Integer b);
}
public class LambdaSample{
public static void main(String[] args){
//1.标准使用方式
MathOperation addition = (Integer a, Integer b)->{
return a+b+0f;
}
addition.operate(5,3);//8.0
//2.Lambda允许忽略参数类型
MathOperation substraction = (a,b)->{
return a-b+0f;
}
substraction.operate(5,3);//2.0
//3.单行实现代码可以省略大括号和return
MathOperation multiplication = (a,b)->a*b+0f;
multiplication.operate(5,3);//15.0
}
}
约束条件:Lambda表达式只能实现有且只有一个抽象方法的接口,Java称为“函数式接口”。
函数式编程是基于函数式接口并使用lambda表达的编程方式。
函数式编程理念是将代码作为可重用数据代入到程序运行中。
函数式编程强调“你想做什么”,而不是“你想怎么做”。
函数式接口是有且只有一个抽象方法的接口。
Java中拥有大量函数式接口,如java.lang.Runnable。
JDK8后提供了一系列新的函数式接口,位于java.util.function。
官方文档:
https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html
JDK8常用函数式接口
可以通过@FunctionalInterface通知编译器这是函数式接口,进行抽象方法检查。
Predicate是新增的函数式接口,位于java.util.function。
Predicate用于测试传入的数据是否满足判断要求。
Predicate接口需要实现test()方法进行逻辑判断。
Predicate案例
public class PredicateSample{
public static void main(String[] args){
Predicate<Integer> predicate = n->n>4;
predicate.test(10);//true
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
/*
for(Integer num:list){
if(num%2==1){
sout(num+" ");
}
}
*/
filter(list, n->n%2==1);//取所有奇数 1 3 5 7 9
filter(list, n->n%2==0);//取所有偶数 2 4 6 8 10
filter(list, n->n>5 && n%2==0);//取所有大于5的偶数 6 8 10
}
public static void filter(List<Integer> list, Predicate<Integer> predicate){
for(Integer num:list){
if(predicate.test(num)){
sout(num+" ");
}
}
}
}
对应有一个输入参数无输出的功能代码。
public class ConsumerSample{
public static void main(String[] args){
output(s->sout("向控制台打印:"+s));
}
public static void output(Consumer<String> consumer){
String text = "abc";
consumer.accept(text);
}
}
对应有一个输入参数且需要返回数据的功能代码。
//利用Function函数式接口生成定长随机字符串
public class FunctionSample{
public static void main(String[] args){
Function<Integer, String> randomStringFunction = l->{
String chars = "qwertyuiopasdfghjklzxcvbnm1234567890";
StringBuffer stringBuffer = new StringBuffer();
Random random = new Random();
for(int i=0; i<l; i++){
int position = random.nextInt(chars.length());
stringBuffer.append(chars.charAt(position));
}
return stringBuffer.toString();
}
randomStringFunction.apply(32);//生成32位长随机字符串
}
}
Stream流式处理是建立在Lambda基础上的多数据处理技术。
Stream对集合数据处理进行高度抽象,极大简化代码量。
Stream可对集合进行迭代,去重,筛选,排序,聚合等一系列处理。
Stream示例
官方文档
https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
Stream流对象的五种创建方式
public class StreamGenerator{
//1.基于数组进行创建
@Test
public void generator1(){
String[] arr = {"Lily","Andy","Jackson","Smith"};
Stream<String> stream = Stream.of(arr);
stream.forEach(s->sout(s));
}
//2.基于集合进行创建
@Test
public void generator2(){
List<String> list = new ArrayList<>();
list.add("Lily");
list.add("Andy");
list.add("Jackson");
list.add("Smith");
Stream stream = list.stream();
stream.forEach(s->sout(s));
}
//3.利用generate方法创建无限长度流,需要和limit配合使用
@Test
public void generator3(){
Stream<Integer> stream = Stream.generate(()->new Random().nextInt(100000));
stream.limit(10).forEach(i->sout(i));
}
//4.基于迭代器创建无限长度流,需要和limit配合使用
@Test
public void generator4(){
Stream<Integer> stream = Stream.iterate(1,n->n+1);
stream.limit(100).forEach(i->sout(i));
}
//5.基于字符序列创建流
@Test
public void generator5(){
String str = "abcdefg";
IntStream stream = str.chars();
stream.forEach(c->sout(c));//会输出每个字符的ANSI码
stream.forEach(c->sout((char)c));//转成char后正常输出字符
}
}
Stream方法案例
public class StreamMethod{
//提取集合中所有偶数并求和
@Test
public void case1(){
List<String> list = Arrays.asList("1","2","3","4","5","6");
int sum = list.stream()//获取stream对象
.mapToInt(s->Integer.parseInt(s))//mapToInt将流中每一个数据转换为整数
.filter(n->n%2==0)//filter对流数据进行过滤
.sum();//求和
sout(sum);//12
}
//所有名字首字母大写
@Test
public void case2(){
List<String> list = Arrays.asList("lily","smith","jackson");
List newList = list.stream()
//map按规则对每一个流数据进行转换
.map(s->s.substring(0,1).toUpperCase()+s.substring(1))
//.forEach(s->sout(s));
//collect对流数据进行收集,生成新的List/Set
.collect(Collectors.toList());
}
//将所有奇数从大到小进行排序,且不允许出现重复
@Test
public void case3(){
List<Integer> list = Arrays.asList(1,23,38,23,34,38,3);
List newList = list.stream().distinct()//去除重复的流数据
.filter(n->n%2==1)
.sorted((a,b)->b-a)
.collect(Collectors.toList());
sout(newList);//[23,3,1]
}
}