lambda与流式编程

什么是lambda表达式

lambda表达式,是Java8的新特性,lambda表达式本质来讲,就是一个匿名函数,使用 Lambda 表达式可以使代码变的更加简洁紧凑。

lambda表达式的语法

  • 基础语法:(参数列表) -> {lambda体}
    以下是lambda表达式的重要特征:
  • **可选类型声明:**不需要声明参数类型,编译器可以通过上下文统一识别出参数类型”。

tips:如果要省略参数的类型,则每一个参数的类型都必须省略。不能出现有些参数写类型,有些参数不写类型。

//接受两个参数(数字),返回值为他们的和 
(x,y) -> y+x
//接受两个int参数(数字),返回值为他们的和 
(int x,int y) -> y+x
  • **可选的参数圆括号:**一个参数可以省略圆括号,但多个参数需要定义圆括号。
//一个参数,返回值为4 
x -> 2+x
//两个参数,返回值为他们的和 
(x,y) -> y+x
  • **可选的大括号:**如果lambda体只包含了一个语句,可以省略大括号,如果是返回语句,则return也省略。
//只有一个语句
x -> 2+x
//只有一个语句
x -> { return 2+x}

lambda表达式的应用

lambda表达式通常用来简化接口的实现,但是只能实现函数式接口

函数式接口:只有一个抽象方法的接口,可以通过使用注解@FunctionalInterface来验证接口是否为函数式接口

下面以Collections的sort方法比较lambda表达式和匿名内部类

//使用匿名内部类
Collections.sort(new ArrayList<String>(), new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        return o1.compareTo(o2);
    }
});

//使用lambda表达式
Collections.sort(new ArrayList<String>(),((o1, o2) -> {
    return o1.compareTo(o2);
}));

可以看到lambda表达式实现这个方法的时候,比匿名内部类更加的简洁。

方法引用

如果在lambda表达式中要实现的功能已经在其他的方法中实现了,我们可以直接引用这个方法

1.静态方法使用类引用,非静态方法使用对象引用
2.只能引用参数、返回值都与接口中的定义一致的方法

public class Test {
    public static void main(String[] args) {
        // 1、静态方法的引用
        ICalculate calc1 = CalculateTest ::calculate1;

        // 2、非静态方法的引用
        // ICalculate calc2 = new CalculateTest () ::calculate2;

        // 3、私有权限在类外不能访问,不能进行方法引用
        ICalculate calc3 = CalculateTest ::calculate3;

        // 4、参数、返回值和接口中定义的方法不完全一致不能引用
        // ICalculate calc4 = CalculateTest ::calculate4;

        // 5、引用Student类中的无参构造方法
        GetStudent get = Student::new;

        // 6、引用Student类中的有参构造方法
        GetStudent2 get2 = Student::new;

        // 7、接口方法参数是一个Person,返回值是String
        GetterTest test = Person::getName;
    }
}

@FunctionalInterface
interface ICalculate {
    int calculate(int a, int b);
}

class CalculateTest {
    public static int calculate1(int a, int b) {
        if (a > b) {
            return a;
        }
        return b;
    }

    public int calculate2(int x, int y) {
        return x + y;
    }

    private static int calculate3(int a, int b) {
        return a + b;
    }

    public void calculate4(int a) {

    }
}

@FunctionalInterface
interface GetStudent {
    Student get();
}

@FunctionalInterface
interface GetStudent2 {
    Student get(String name, int age);
}

class Student {
    public Student() { }
    public Student(String name, int age) {

    }
}

@FunctionalInterface
interface GetterTest {
    String getName(Person person);
}

class Person {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

四大核心函数式接口

消费型接口:Consumer

方法:void accept(T t);

无返回值,常用于打印等消费操作

/**
 * 控制台打印 5
 */
public void testConsumer() {
	handle(5, (x) -> System.out.println(x));
}
public void handle(int value, Consumer<Integer> consumer) {
	consumer.accept(value);
}

供给型接口:Supplier

方法:T get();

常用于获取结果

/**
 * 控制台打印 张三
 */
public void testSupplier() {
	Person person = new Person ();
        person.setName("张三")
	System.out.println(getObject(() -> person.getName()));
}
public String getObject(Supplier<String> supplier) {
	return supplier.get();
}

函数型接口:Function<T,R>

方法:R apply(T t);

传入一个参数T,返回一个结果R

public void testFunction() {
        //删除单数
	System.out.println(oneTwo(1, (x) -> {
            if (x%2==0){
                return "双数";
            }
            return "单数";
        }));

        //删除双数
	System.out.println(oneTwo(2, (x) -> {
            if (x%2==0){
                return "双数";
            }
            return "单数";
        }));
	
	// 输出62
        System.out.println(before(6, x -> x + 2, x -> x * 10));

        // 输出80
        System.out.println(after(6, x -> x + 2, x -> x * 10));
}
public Integer oneTwo(int origen, Function<Integer, String> function) {
	return function.apply(origen);
}
public Integer before(int value, Function<Integer, Integer> function1, Function<Integer, Integer> function2) {
	// value作为function2的参数,返回一个结果,该结果作为function1的参数,返回一个最终结果
	return  function1.compose(function2).apply(value);
}
public Integer after(int value, Function<Integer, Integer> function1, Function<Integer, Integer> function2) {
	// value作为function1的参数,返回一个结果,该结果作为function2的参数,返回一个最终结果
	return  function1.andThen(function2).apply(value);
}

断言型接口:Predicate

方法:boolean test(T t);

接受一个输入参数T,返回一个布尔值结果,常用于条件判断

public void testPredicate() {
	//输出false
	System.out.println(judge(1, (x) -> x != 1));

        //输出true
	System.out.println(judge(1, (x) -> x = 1));
}
public boolean judge(Integer input, Predicate<Integer> predicate) {
	return predicate.test(input);
}

流式编程Stream API

Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据

Stream(流)是一个来自数据源的元素队列,但是这个队列并不会存储元素,而是按需计算
数据源可以是集合,数组,I/O channel, 产生器generator 等

通常情况下,使用流式编程,需要经过以下三步。

1、创建流

获取数据源,将数据源中的数据读取到流中

List list = new ArrayList();
//为集合创建串行流
Stream stream = list.stream();
//为集合创建并行流 集成了多个线程对流中的数据进行操作,效率更高
Stream stream = list.parallelStream();

2、中间操作

对流中的数据进行各种各样的处理,每一个操作的返回值都是一个Stream对象,可以继续进行其他的操作,直到最终操作

//filter  条件过滤,仅保留流中满足指定条件的数据,其他不满足的数据都会被删除
list.stream().filter(e -> e.length() > 5).forEach(System.out::println);

//distinct  去重集合中重复的元素。这个方法没有参数。去重的规则与HashSet相同
list.stream().distinct().forEach(System.out::println);

//sorted  将流中的数据进行排序
// Comparable 接口方法实现排序
list.stream().sorted().forEach(System.out::println);
// 指定规则排序
list.stream().sorted((e1, e2) -> e1.length() - e2.length()).forEach(System.out::println);

//limit  截取流中指定数量的元素
list.stream().limit(2).forEach(System.out::println);

//skip  跳过流中的指定数量的元素
list.stream().skip(2).forEach(System.out::println);

//map  对流中的数据进行映射,用新的数据替换旧的数据
list.stream().map(e -> e + "添加").forEach(System.out::println);

//flatMap  扁平化映射 
//方法返回一个Stream
public Stream<String> method(...){...}
//map
Stream<Stream<String>> list.stream().map(对象::method);
//flatMap  
Stream<String> list.stream().map(对象::method);

3、最终操作

对流中的数据进行整合处理,并关闭流,因此最终操作只能存在一个

//collect  将流中的数据收集到一起进行处理
//将list转成set
Set<Integer> result = list.stream().collect(Collectors.toSet());
System.out.println(result);

//reduce  将流中的数据按照一定的规则聚合起来
int result = list.stream().reduce((e1, e2) -> e1 + e2).get();
System.out.println(result);

//count  统计流中的元素数量
int result = list.stream().count();
System.out.println(result);

//forEach  迭代流中的数据
list.stream().forEach(System.out::println);

//max  获取流中的最大元素
int result = list.stream().max(Integer::compareTo).get();
System.out.println(result);

//min  获取流中的最小元素
int result = list.stream().min(Integer::compareTo).get();
System.out.println(result);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值