【JDK专题】——JDK特性——StreamApi操作

JDK——Lambada表达式——启示录

在Java中,因为语法强类型以及面向对象语法的约束;任何方法必须属于某个对象或者是某个类(静态方法),因此就导致了在函数式编程上出现了困难;
而如果你开发过javaScript的话,这种弱类型编程语言,你将会体验到它的好处;比如:

var print=function(){
	console.log("111111")
}
var invoke=function(fun){
	fun();
}
//把函数传给函数,在内部调用
invoke(print)
invoke(()=>{//匿名函数对象
	console.log("111111")
})
//简写

Ps:显然以上情形在java是做不到的,只能把对象传给方法,然后再调用对象的方法;如果能用一种机制能在java中抽象出函数对象这个概念,那么实现这种函数式编程就有了很大的帮助;

JDK——Lambada表达式——具体用法

为了解决函数式编程问题,jdk1.8推出函数式接口+lambada表达式–这两个组合,来帮我们解决函数式编程的问题,编译器最终会将lambada函数表达式的内容实例化成函数式接口的类型,实际上最后也是作为对象的方法调用,只是这一个过程编译器自动帮我们做好了;

函数编程第一步(声明函数式接口) 告诉编译器,我们函数的参数类型以及返回值类型;

public interface MyFunction {
    public void apply(int i);
}

函数编程第二步(方法参数是函数接口)

public class MyArray {
    private int index=0;
    private int[] data=new int[5];
    public void add(int i){
        data[index]=i;
        index++;
    }
    /**
     * @MyFunction
     * 接口外部利用lambada形式构成的函数
     * 编译器会将lamabda与接口构成一个匿名类和对象,
     * 所以此时的function就是一个对象,以MyFunction作为原型;lambada作为内容,组合在一起生成的
     * 我们这个案例是模拟forEach的写法
     */
    public void forEach(MyFunction function){
        for(int item:data){
            function.apply(item);
        }
    }
}

在这里插入图片描述

函数编程第三步(运用lambada表达式)

public class test01 {
    public static void main(String[] args) throws  Exception {
        MyArray myArray=new MyArray();
        myArray.add(1);
        myArray.add(2);
        myArray.add(3);
        myArray.add(4);
        /**
         * 应用一(一般这么用)
         * lambad的内容+函数原型=匿名函数类+匿名函数对象,在方法内部被调用
         */
        myArray.forEach(item->{
            System.out.println(item);
        });
        /**
         * 应用二(不这么用)
         */
        MyFunction function=(item)->{
            System.out.println(item);
        };
        myArray.forEach(function);
    }
}

JDK——Lambada表达式——内置函数接口

很显然,一些通用的函数接口,比如:遍历、过滤;这些jdk8已经原生帮我们实现了;
Function函数接口(函数对象,具有返回值也有参数值)

【基本原型】
Function<Integer, Integer> funA = (item) -> {//声明 左边参数类型;右边返回值类型,只能接受一个参数
    return item + 5;
};
funA.apply(1);//普通调用
【应用举例】
public class MyArray {
    public void invokeFunction(Function<Integer,Void> function,Integer functionArgs){
        function.apply(functionArgs);
    }
}
public class test01 {
    public static void main(String[] args) throws  Exception {
        MyArray myArray=new MyArray();

        /**
         * 应用一(一般这么用)
         */
        myArray.invokeFunction(item->{
            System.out.println(item);
            return null;
        },5);
        /**
         * 应用二(不这么用)
         */
        Function<Void,Integer> function=(item)->{
            System.out.println(item);
            return null;
        };
         myArray.invokeFunction(function)
    }
}
Ps:java中lambada表达式在函数编程中无法实现静态函数传参
【Function扩展】————一般没啥用
Function<Integer, Integer> funB = i -> i * i;
Function<Integer, Integer> funC = i -> i * i;
Function<Integer, Integer> funD = i -> i * i;
funB.compose(funB).compose(funC).compose(funD).apply(5);//从最右边函数apply传一个常量结果递归传到前面
funB.andThen(funB).andThen(funC).andThen(funD).apply(6);//从左边函数apply传一个常量结果递归传到后面

Consumer 消费者接口(只有参数没返回值的函数对象)

只传参不返回值
Consumer<String> consumer = s -> System.out.println(s);//声明,无返回值。泛型参数类型
consumer.accept("helloWorld!");//调用

**Supplier提供者接口(没有参数有返回值的函数对象)**

```java
不传参,就有返回值
Supplier<String> supplier = () -> "HelloWorld!";//声明,无参数,有返回值;泛型返回值类型
System.out.println(supplier.get());

Predicate 校验接口(校验对象是否符合要求的函数对象,返回布尔值)

返回布尔值,可以嵌套校验
Predicate<Integer> predicateA = item -> item > 3;
Predicate<Integer> predicateB = item -> item > 3;
Predicate<Integer> predicateC = item -> item > 1;
Predicate<Integer> predicateD = item -> item > 1;
Predicate<Integer> predicateE = item -> item > 1;//声明

boolean checkResult = predicateA//统一对一个数据类型进行校验;最后返回整体校验的布尔值!
        .and(predicateB)
        .and(predicateC)
        .or(predicateD)
        .negate().test(num);//test是传参,negate是非逻辑

举例


public class MyArray {
    private int index=0;
    private int[] data=new int[5];
    public void add(int i){
        data[index]=i;
        index++;
    }
    public void consumerArray(Consumer<Integer> consumer){
        for(int item:data){
            consumer.accept(item);
        }
    }
    public String providerArray(Supplier<String> supplier){
        String all="";
        for(int item:data){
            all=all+String.valueOf(item)+supplier.get();
        }
        return all;
    }
    public void checkrArray(Predicate<Integer> predicate){
        for(int item:data){
            predicate.test(item);
        }
    }
}

public class test01 {
    public static void main(String[] args) throws  Exception {
        MyArray myArray=new MyArray();
        myArray.add(1);
        myArray.add(2);
        myArray.add(3);

        /**
         * 提供一个函数,利用某些特定机制返回前缀,然后将所有数组拼接返回
         */
        String joinResult = myArray.providerArray(() -> "GodShcool");

        /**
         * 提供一个函数,然后将数组遍历对元素输出
         */
        myArray.consumerArray(item-> System.out.println(item));
        /**
         * 提供一个函数校验,设定boolean规则,校验是否符合要求
         */
        myArray.checkrArray(item->item>3);
    }
}

Comparator比较接口

根据布尔值,返回三种值,>0,<0,-0的
Comparator<Person> comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName);
Person p1 = new Person("John", "Doe");
Person p2 = new Person("Alice", "Wonderland");
comparator.compare(p1, p2);

JDK——Lambada表达式——方法引用

有的时候我们的函数可能已经在某个类中写好了,就不需要每次手动写,避免麻烦,利用方法引用多次引用一个类中的函数,编译器会将此自动组合;

将lambada写在在一个公共的类里
public class Common {
    public static void comsumerItem(Integer item){
        System.out.println(item);
    }
}
public class test01 {
    public static void main(String[] args) throws  Exception {
        MyArray myArray=new MyArray();
        myArray.add(1);
        myArray.add(2);
        myArray.add(3);
        myArray.consumerArray(Common::comsumerItem);
        myArray.consumerArray(System.out::print);//引用System.out的print方法作为lambada
        
    }
}
引用构造器的代码	   Function<Integer,Integer[]>fun=Integer[]::new
Ps:还可以引用实例对象的代码,反正只需要记住代码只是作为lambada原型就行

JDK——Lambada表达式——StreamApi

列表流操作:

/**
    * @创建流
    */
   List<Integer> intList=new ArrayList<>();
   int[] intArr=new int[]{1,2,3,4,5};
   IntStream intStream=Arrays.stream(intArr);//数组流
   Stream<Integer> stream=intList.stream();//集合流
   Stream<Integer> s=Stream.of(1,2,3,4);//常量流
   Stream<String>b= Files.lines(Paths.get("data.txt"), Charset.defaultCharset());//文件流
   /**
    * @简单中间操作
    */
   intList.stream()
      .filter(i->{//过滤剩下的元素
       return  i>3;
   }).distinct()//去重复
     .skip(1)//跳过多少页
     .limit(20);//指定个数
 /**
    * @简单终端操作
    */
   intList.stream().count();//计算数量
   intList.stream() .findFirst();//返回第一个元素
   intList.stream() .findAny();//随机返回一个元素
   /**
    * @返回集合
    */
   List<Integer> intListCollect = intList.stream().collect(Collectors.toList());
   Set<Integer> intSetCollect = intList.stream().collect(Collectors.toSet());
   String intStringJoinCollect = stream.map(i->String.valueOf(i)).collect(Collectors.joining(","));
   /**
    * @统计操作
    */
   List<Dish> dishList=new ArrayList<>();
   dishList.stream().map(Dish::getCalories).min(Integer::compareTo);
   dishList.stream().map(Dish::getCalories).max(Integer::compareTo);
   Integer sum = dishList.stream().collect(Collectors.summingInt(Dish::getCalories));
   Double avg = dishList.stream().collect(Collectors.averagingInt(Dish::getCalories));
   IntSummaryStatistics collect2 = dishList.stream().collect(Collectors.summarizingInt(Dish::getCalories));
   collect2.getAverage();
   collect2.getCount();
   collect2.getMax();
   collect2.getSum();
   collect2.getMin();
   Integer reduce = stream.reduce(0, (old, item) -> (old + item));//利用数组流的元素对目标值进行改造,返回新的改造结果
   /**
    * @分组,分区
    * 分区特殊的分组,只以boolean区分;
    */
   Map<Boolean, List<Dish>> partitioningListMap=dishList.stream().collect(Collectors.partitioningBy(Dish::isVegetarian));
   Map<Type, List<Dish>> groupListMap= dishList.stream().collect(Collectors.groupingBy(Dish::getType));
   /**
    * @返回布尔值
    */
   boolean b1 = stream.allMatch(i -> i > 3);//全部都匹配返回true
   boolean b2 =stream.anyMatch(i->i>3);//任意一个匹配返回true
   boolean b3 =stream.noneMatch(i->i>3);//全部不匹配返回true

列表映射操作(简单映射):

需求:
public class test01 {
    public static void main(String[] args) throws  Exception {
      /**
         * 需求:取出列表中的每个对象的username组成一个新列表
         */
        List<User> users=new ArrayList<>();
        users.add(new User());
        users.add(new User());
        users.add(new User());
        users.add(new User());
        users.add(new User());
    }
}
实现:
public class test01 {
    public static void main(String[] args) throws  Exception {
        /**
         * 需求:取出列表中的每个对象的username组成一个新列表
         */
        List<User> users=new ArrayList<>();
        users.add(new User());
        users.add(new User());
        users.add(new User());
        users.add(new User());
        users.add(new User());
        /**
         * streamApi中链式操作的返回值,就是为每个数组的元素映射成一个新对应对象
         * 最后组成一个数组
         */
        List<String> collect = users.stream().map(item -> {
            return item.getUsername();
        }).collect(Collectors.toList());
    }
}

结果:

在这里插入图片描述
列表映射操作(嵌套映射):

public class User {
    private String username;
    private String password;
    private List<Role> roles;
    public User(){
        this.username="11111";
        this.password="*****";
        this.roles=new ArrayList<>();
        roles.add(new Role());
        roles.add(new Role());
        roles.add(new Role());
        roles.add(new Role());
    }

    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

}
public class Role {
    private String roleName;
    private String roleCode;
    public Role(){
        this.roleName="admin";
        this.roleCode="00000";
    }
    public String getRoleName() {
        return roleName;
    }
    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }
}
测试:
public class test01 {
    public static void main(String[] args) throws  Exception {
        /**
         * 需求:取出列表中的roles的列表中roleName并组成一个新的数组
         */
        List<User> users=new ArrayList<>();
        users.add(new User());
        users.add(new User());
        users.add(new User());
        users.add(new User());
        users.add(new User());
        /**
         * flatMap可以继续映射数组中的数组的流,并将数据拿出来并组成新数组
         */
        List<String> collect = users.stream()
                .flatMap(user -> user.getRoles().stream())
                .map(role -> role.getRoleName())
                .collect(Collectors.toList());
    }
}

结果:

在这里插入图片描述

JDK——Lambada表达式——Optional

StreamApi一般返回是都是Optional类型的对象,这是一个可以安全操作的对象,可以优雅的避免空指针异常;

/**
 * 【创建Optional装饰器对象】
 */
Optional.empty();//空的 Optional 实例
Optional.ofNullable(null);//空的 Optional 实例
Optional.ofNullable(new Employee());//有值的 Optional 实例
Optional<Employee> op = Optional.of(new Employee(101, "张三", 18, 9999.99));//静态创建
/**
 * 【获取值】,空指针则返回null
 */
op2.get();
op3.get();
/**
 * 【安全调用】,空指针则不执行任何事情
 */
 Optional.ofNullable(student).ifPresent(u ->  System.out.println("The student name is : " + u.getName()))
 /**
 * 【Strema举例安全调用举例】
 */
  Cookie[] cookies = request.getCookies();
        if(cookies!=null){
           Optional<String> result = Arrays.stream(cookies)
                    .filter(cookie -> "sessionId".equals(cookie.getName()))
                    .map(cookie -> cookie.getValue())
                    .findFirst();
           result.ifPresent(sessionId->{
               template.header("sessionId",sessionId);
           });
        }

GodSchool
致力于简洁的知识工程,输出高质量的知识产出,我们一起努力

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值