Lambda表达式和函数式编程

Lambda 表达式的语法与使用:更简洁、更灵活的函数式编程! 哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛 阅读详情

一.函数式编程概念

(a,b) -> {xxx} 

参数 -> 方法体 左侧一个参数时()可以省略,右侧就一句方法体时{}可以省略

二.JDK8引入的函数是编程接口类

要想学习函数式编程一定要知道jdk提供的四种类型的函数式编程接口

1.Function<T, R>  该类型的方法接收一个T类型的参数,返回一个R类型的结果
2.Consumer<T>  该类型方法接收一个T类型的参数,无返回值
3.Supplier<T>  该类型方法不接收任何参数,返回一个T类型结果
4.Predicate<T>  该类型方法接收一个T类型的参数,返回一个Boolean类型返回值
5.Optional<T> 该类型方法既主要在lambda函数式编程中处理空值情况

三.流的创建方式

1.数组转流(Arrays.stream())

    int[] a = {1,2,3};
    Arrays.stream(a).peek(e -> log.info(e)).collect(Collectors.toList());

2.集合类型转流(Collection.stream())

    List<User> userList = new ArrayList<>();
    userList.stream().peek(user -> log.info(user)).collect(Collectors.toList());

3.任意类型对象转流(Stream.Of())

添加不同类型的对象会变成一个Object类型的流

Stream.of(1,2,3).peek(e -> log.info(e)).collect(Collectors.toList());

4.迭代器添加元素转流(Stream.iterate())

迭代器内第一个参数为初始值,第二个参数为一个lambda表达式,因为这个循环是个死循环所以这边limit了前10个元素

Stream.iterate(0,n -> n+1).limit(10).peek(e -> log.info(e)).collect(Collectors.toList());

5.generate生成流(Stream.generate())

迭代器内第一个参数为一个lambda表达式,因为这个循环是个死循环所以这边limit了前10个元素

Stream.generate(() -> Math.random()).limit(10).peek(e -> log.info(e)).collect(Collectors.toList());

6.StreamSupport生成流(Stream.generate())

其实集合转流的方式底层就是用的StreamSupport生成流的方式,大家可以去源码看下

Stream.generate()生成流的方式不常用,因为一般我们操作集合数组时直接用JDK封装好的转流方式就可以了,这边不做演示。
该方法有两个参数,第一个参数是迭代器Spliterator对象,第二个参数是是否启用并行流的true/false值

7.IntStream整形流

IntStream继承了BaseStream,有基础的流操作功能等

IntStream.range(0,5).boxed().peek(e -> log.info(e)).collect(Collectors.toList());
range()左闭右开,rangeClosed()左右都是闭区间,boxed()方法将基本类型转包装类型

8.Stream.builder()构造器生成流

Stream.builder()这种方式需要最后调用build()方法,本质上和Stream.Of()相同

Stream.Builder<User> userBuilder= Stream.builder();
userBuilder.add(new User()).add(new User()).add(new User()).build().collect(Collectors.toList());

四.常见操作符

1.中间操作符

User对象,假设User对象具有id,name,age三个属性,下面的例子以操作User对象为例

User user = new User();
List<User> userList = new ArrayList<>();

filter():过滤符合条件的数据流传给下层操作符处理

Optional<User> user1 = userList.stream().filter(user -> user.getAge() > 20).findFirst();

map():遍历数据,可在map中将原始对象转换为其他类型对象后返回新对象数据流传给下层操作符操作

userList.stream().map(User::getName).collect(Collectors.toList());

peek():一般用于打印流操作中间状态的元素详情等,一般并无实际意义

比较简单不做演示了

findAny():返回流中的第一个元素,在串行流中和findFirst()功能一样,在并行流中返回的是最快处理完的那个线程的数据,所以说在并行流操作中,对数据没有顺序上的要求,那么findAny的效率会比findFirst要快的

Optional<User> user2 = userList.stream().filter(user -> user.getAge() > 20).findAny();

findFirst(): 返回流中的第一个元素

Optional<User> user1 = userList.stream().filter(user -> user.getAge() > 20).findFirst();

sorted():排序,数字类型默认升序,中文和英文等按字典序排序,可以传入自定义的比较器(两个对象比较返回负数是升序,返回正数是降序,返回0为相等比较器会做去重操作), 此外自定义Compartor比较器排序后如果收集为不具备插入顺序的数据结构中是不能保证sorted()排序后的顺序的, 相当于没排序!!!

userList.stream().sorted().collect(Collectors.toList());
userList.stream().sorted(Compartor.reverseOrder()).collect(Collectors.toList());

// 下面演示自定义比较器
Map<String, Integer> map = new HashMap<>();
map.put("ihi", 1);
map.put("wang", 3);
map.put("li", 2);
map.put("abu", 4);
map.put("jia", 2);

// 降序 -1升序 1降序 0相等 自定义比较器的匿名实现类实现
map.entrySet().stream().sorted(new Comparator<Map.Entry<String, Integer>>() {
                    @Override
                    public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                        if (o1.getValue() >= o2.getValue()) {
                            return -1;
                        }
                        return 1;
                    }
                }).forEach(e -> {
                    System.out.println(e.getKey() + e.getValue());
                });
          
 // 升序 -1升序 1降序 0相等 自定义lambda方式的匿名实现类实现
map.entrySet().stream().sorted((o1, o2) -> {
                    if (o1.getValue() >= o2.getValue()) {
                        return 1;
                    }
                    return -1;
                })
                .forEach(e -> {
                    System.out.println(e.getKey() + e.getValue());
                });
// sorted 后收集为map和set都不能使用sorted排好的顺序,想有顺序可以用TreeMap或LinkhashMap
        map.entrySet().stream()
                .sorted((o1, o2) -> {
                    if (o1.getValue() >= o2.getValue()) {
                        return 1;
                    }
                    return -1;
                })
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
 
// sorted 后收集为map和set都不能使用sorted排好的顺序, 可以使用LinkedHashSet代替
        map.entrySet().stream()
                .sorted((o1, o2) -> {
                    if (o1.getValue() >= o2.getValue()) {
                        return 1;
                    }
                    return -1;
                })
                .collect(Collectors.toCollection(LinkedHashSet::new));

// sorted 后收集为list就可以使用排好的顺序
List<Map.Entry<String, Integer>> collect = map.entrySet().stream()
                .sorted((o1, o2) -> {
                    if (o1.getValue() >= o2.getValue()) {
                        return -1;
                    }
                    return 1;
                })
                .collect(Collectors.toList());

// sorted可以使用对象的compareTo()方法比较
map.entrySet().stream().sorted(
                        (o1, o2) -> o2.getValue().compareTo(o1.getValue()))
                .forEach(e -> {
                    System.out.println(e.getKey() + "-------" + e.getValue());
                });
                
        List<Map.Entry<String, Integer>> collect = map.entrySet().stream()
                .sorted((o1, o2) -> {
                    if (o1.getValue() > o2.getValue()) {
                        return -1;
                    }else if (o1.getValue() < o2.getValue()){
                        return 1;
                    }
                    return 0;
                }).collect(Collectors.toList());
lambda表达方式排序:
List<PurchaseActionDetail> collect = Stream.of(purchaseActionDetail1, purchaseActionDetail2, purchaseActionDetail3, purchaseActionDetail4)
                .collect(Collectors.toList())
                .stream()
                .sorted(
                        Comparator.comparing(PurchaseActionDetail::getActionType,((o1, o2) -> o2 -o1)).thenComparing(e -> Integer.parseInt(e.getActionTime()), (o1,o2) -> o2 - o1)
                )
                .collect(Collectors.toList());

flatMap():参数是流,主要使用场景是处理高阶嵌套的流,将高阶流扁平化。例如:父子对象常见的集合属性

第一个应用场景:一个用户可能有多重角色,典型一对多父子类型

userList.stream().flatMap(user -> user.getRoles().stream()).peek(role -> log.info(role)).collect(Collectors.toList());

第二个应用场景:在流中产生了Optional元素,想要取出Optional中的具体类型对象来操作

此时假设角色集合返回的是Optional<List<Role>>类型
userList.stream().map(user->user.getRoles().stream()).flatMap(Optional::stream).peek(role->log.info(role)).count());

2.终端操作符(count、min、max具有统计意义)

User对象,假设User对象具有id,name,age三个属性,下面的例子以操作User对象为例

User user = new User();
List<User> userList = new ArrayList<>();

forEach():遍历集合,非并行流时流中的元素是顺序性的,并行流时流中的元素不能保证是顺序性的

将所有用户的年龄都改为20岁
userList.stream().forEach(user -> user.setAge(20));

forEachOrder():遍历集合,主要用于在并行流中想按排序的顺序操作流中元素,如果不是并行流那么forEachOrder和forEach没有任何区别

按年龄大小输出用户名称
userList.parallelStream().sorted(Comparator.comparing(User::getAge)).forEachOrdered(user -> log.info("用户名称" + user.getName()));

anyMatch():集合中有任何一个满足条件的数据就会返回true,反之返回false(存在短路的优点有结果了就会返回,不会继续遍历下去)

boolean result = userList.stream().anyMatch(user -> user.getAge() > 20);
如果anyMatch()方法中的函数体很长也可以这样操作
Predicate<User> predicate = user -> user.getAge() > 20;
boolean result = userList.stream().anyMatch(predicate);

allMatch():集合中所有数据都满足条件的数据才会返回true,任意一条数据不满足条件都会返回false

集合中有任何一个满足条件的数据就会返回true,反之返回false
boolean result = userList.stream().anyMatch(user -> user.getAge() > 20);
如果allMatch()方法中的函数体很长也可以这样操作
Predicate<User> predicate = user -> user.getAge() > 20;
boolean result = userList.stream().allMatch(predicate);

noneMatch():集合中没有任何一个匹配条件的元素时返回true,反之返回false

boolean result = userList.stream().noneMatch(user -> user.getAge() > 20);
如果noneMatch()方法中的函数体很长也可以这样操作
Predicate<User> predicate = user -> user.getAge() > 20;
boolean result = userList.stream().noneMatch(predicate);

count():统计满足条件的用户数

long count = userList.stream().filter(user -> user.getAge() > 20).count();

min():排序后取出最小的用户数据

Optional<User> min = userList.stream().min(Comparator.comparing(User::getAge));

max():排序后取出最大的用户数据

Optional<User> max = userList.stream().max(Comparator.comparing(User::getAge));

reduce():执行归集操作,某种程度上和Collect作用类似,设计上reduce应该和不可变得对象一起工作,如果对象是可变的,也可以得到结果,但是不是线程安全的,性能要弱于Collect,但是很灵活

第一个参数是初始值(可以不设置,不设置默认流中的第一个元素为初始值),第二个参数是个函数,函数的第一个参数是累加器,第二个参数是当前值,第三个参数是在并行流时会每个分片处理的线程会有一个临时的值,这个参数为合并策略。

累加器什么意思呢?就是第一次进来累加器取初始值,然后每次循环用当前的值加在累加器上,累加器相当于值得总和,reduce也是循环处理对象的

userList.stream().map(User::getAge).reduce(0,(Integer acc, Integer curr)-> Integer.sum(acc,curr));

userList.parallelStream().reduce(
                Collections.EMPTY_LIST,
                
                (acc,curr) ->{
                    List<User> newAcc = new ArrayList<>();
                    newAcc.addAll(acc);
                    newAcc.addAll(curr);
                    return newAcc;
                },
                
                (left,right)->{
                    List<User> merged = new ArrayList<>();
                    merged.addAll(left);
                    merged.addAll(right);
                    return merged;
                }
        );

3.常见集合对象收集器

toList():将结果收集为一个List集合

Stream.iterate(0,n -> n+1).collect(Collectors.toList());

toSet():将结果收集为一个Set集合,Set集合元素不会重复

Stream.iterate(0,n -> n+1).collect(Collectors.toSet());

toMap():将结果收集为一个Map集合,键值对的形式,收集为Map集合时,有3种参数类型的重载方法可选

2个参数的情况,toMap()中的第一个参数代表要收集Map结构的key,第二个参数代表要收集Map结构的value
其中Function.identity()和user -> user是等价的它代表输入和输出相同是Function中的一个静态方法(大家可以看下源码)

userList.stream().collect(Collectors.toMap(User::getId, user -> user));
userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));

3个参数的情况,toMap()中的第三个参数代表当Key产生了重复值,那么在第三个参数方法中处理(用于合并的方法参数)

userList.stream().collect(Collectors.toMap(User::getId, user -> user, (oldValue,newValue) -> oldValue));

4个参数的情况,toMap()中的第四个参数代表构建Map的工厂,一般用于不想返回系统默认的HashMap结构,比如返回TreeMap等

userList.stream().collect(Collectors.toMap(User::getId, user -> user, (oldValue,newValue) -> oldValue, TreeMap::new));

toCollection():将结果收集为一个自定义的集合类型

TreeSet treeSet = userList.stream().collect(Collectors.toCollection(() -> new TreeSet(Comparator.comparing(User::getAge))));

4.收集器中的聚合计算,分组统计和收集器

首先我们来说下收集器中的聚合函数哈,虽然在数据库层面提供了分组,求平均值,计算数量,最大值,最小值等功能,但不代表我们没有在Lambda中完成上述操作的需求,因为毕竟是在内存中完成的聚合计算,有的时候性能会比数据库层面要提升很多

averagingXXX():求平均值,可以转为3中数字类型(Double,Integer,Long)

所有用户年龄的平均值
Integer aveAge = userList.stream().collect(Collectors.averagingInt(User::getAge));
Double aveAge = userList.stream().collect(Collectors.averagingDouble(User::getAge));
Long aveAge = userList.stream().collect(Collectors.averagingLong(User::getAge));

summingXXX():求和,可以转为3中数字类型(Double,Integer,Long)

Integer aveAge = userList.stream().collect(Collectors.summingInt(User::getAge));
Double aveAge = userList.stream().collect(Collectors.summingDouble(User::getAge));
Long aveAge = userList.stream().collect(Collectors.summingLong(User::getAge));

counting():计数,计算满足条件的对象或值的数量

Map<String, Long> stringLongMap = userList.stream().collect(Collectors.groupingBy(User::getName, Collectors.counting()));

maxBy():取最大值,方法中需要传进去一个比较器,不然它不知道按哪一个值比较大小,返回一个Optional对象

Optional<User> user = userList.stream().collect(Collectors.maxBy(Comparator.comparing(User::getAge)));

minBy():取最小值,方法中需要传进去一个比较器,不然它不知道按哪一个值比较大小,返回一个Optional对象

Optional<User> user = userList.stream().collect(Collectors.minBy(Comparator.comparing(User::getAge)));

summarizingXXX():为了方便我们操作,这个方法里统计了上面所有的值,返回一个XXXSummaryStatistics对象,我们可以按需取值

IntSummaryStatistics intSummaryStatistics = userList.stream().collect(Collectors.summarizingInt(User::getAge));
LongSummaryStatistics longSummaryStatistics = userList.stream().collect(Collectors.summarizingLong(User::getAge));
DoubleSummaryStatistics doubleSummaryStatistics = userList.stream().collect(Collectors.summarizingDouble(User::getAge));

groupingBy():以某一个值分组,默认返回一个Map,groupingBy方法中可以继续下一步的流操作(downstream),一般在业务中和mapping连用比较多

User对象转为UserDto对象:

Map<Long, List<UserDto>> map = userList.stream().collect(Collectors.groupingBy(
                User::getId,
                Collectors.mapping(
                        user -> new UserDto(user.getId(), user.getName(), user.getAge()),
                        Collectors.toList())
        ));

区域仓地址信息按省份id分组后计算市区的数量:

Map<Long, Long> cityCountMap = Optional.ofNullable(warehouseInfo.getAddr()).orElse(new ArrayList<>()).stream().collect(Collectors.groupingBy(WarehouseAddr::getAddrId1, Collectors.counting()));

区域仓地址信息按省份id分组后将市区组装为一个List集合

Map<Long, List<Long>> haveStockAreaMap = Optional.ofNullable(warehouseInfo.getAddr()).orElse(new ArrayList<>()).stream().collect(Collectors.groupingBy(WarehouseAddr::getAddrId1, Collectors.mapping(
WarehouseAddr::getAddrId2, Collectors.toList())));

partitioningBy():partitioningBy和groupingBy都是用于将数据进行分组的函数。
两者的区别主要是参数返回值不同,partitioningBy又被称为分区函数,返回TRUE / FALSE两组数据,重载的分区函数可以传递下游流操作,比如继续分组等

看源码可以看出函数的参数一个Predicate接口,那么这个接口的返回值是boolean类型的,也只能是boolean类型,然后他的返回值是Map的key是boolean类型,也就是这个函数的返回值只能将数据分为两组也就是ture和false两组数据。
public static <T>
    Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) {
        return partitioningBy(predicate, toList());
    }
    
public static <T, D, A>
    Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,
                                                    Collector<? super T, A, D> downstream){
                                                    }
                                                    
public static <T, K> Collector<T, ?, Map<K, List<T>>>
    groupingBy(Function<? super T, ? extends K> classifier) {
        return groupingBy(classifier, toList());
    }

joining():主要用于字符串的连接,一般用3个参数的重载方法,第一个参数是以"符号”连接每个对象,第二个参数是整体返回对象的前缀,第三个参数是整体返回对象的后缀

以一个拼接访问参数为例:

Map<String,String> paramMap = new HashMap();
paramMap.put("name","张三");
paramMap.put("age","20");
paramMap.put("email","123@qq.com");
paramMap.keySet().stream().map(key - > key + "=" paramMap.get(key)).sorted().collect(Collectors.joining("&","http://localhost:8080/api?",""))

mapping():和常用中间操作符map()功能类似,第二个参数为下游流操作函数,主要处理中间类型转换等,可以一直用流操作串下去

List<String> list = Lists.newArrayList("bb", "ddd", "cc", "a");
Map<Integer,TreeSet<String>> result = list.stream().collect(
                Collectors.groupingBy(
                        String::length,
                        Collectors.mapping(
                                String::toUpperCase,
                                Collectors.filtering(
                                        s -> s.length() > 1,
                                        Collectors.toCollection(TreeSet::new)
                                ))));

collectingAndThen():一般用于先收集一个集合后,再对收集后的集合做一些操作

Map<String, Double> collect1 = userList.stream().collect(
                Collectors.groupingBy(
                        User::getName,
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                e -> {
                                    return e.stream().collect(Collectors.averagingDouble(User::getAge));
                                }
                        )
                ));

reducing():和reduce操作类似

五.Optional流操作

Optional是Java8新增的在java.util包下,主要用来辅助处理Java流式操作中的null值,它在返回结果之上又封装了一层,封装的这层永远不会出现null值,来确保我们在用lambda流操作时不会中断

1.生成Optional对象的方式

因为其构造方法是私有的,所以只能通过静态的构造器来创建Optional对象

Optional.<>of():生成Optional对象,接收的对象不能为null否则抛出NullPointerException异常

Optional.of(userList).ifPresent(users -> users.stream().filter(user -> user.getAge() > 20).count());

Optional.<>ofNullable():生成Optional对象,接收的对象可以为null,如果为null则内部返回Optional.<>empty()对象

Optional.ofNullable(userList).orElse(new ArrayList<>());

Optional.<>empty():生成一个空Optional对象,源码注释上写着不能保证这个对象是单例的,具体原因还没搞清,各位有懂得可以评论区为笔者解答下(笑出鹅叫)

2.Optional常见操作符

isPresent:判断Optional值是否存在,存在返回true,不存在返回false

boolean present = Optional.ofNullable(userList).isPresent();
 if (present){
     //TODO 业务逻辑
 }
 else {
     //TODO 业务逻辑
 }

orElse:Optional的值为null时,要返回的常量值或对象

Optional.ofNullable(userList).orElse(new ArrayList<>());

orElseGet:Optional的值为null时,要执行一个方法并返回一个值

Optional.ofNullable(userList).orElseGet(()->new ArrayList<User>());

orElseThrow:Optional的值为null时,要抛出的异常

Optional.of(userList).orElseThrow(()->new Exception());

or:Optional的值为空时,我们既不抛异常也不返回一个默认值下面的操作还要返回一个Optional对象时用or

ifPresent:如果Optional的值存在,下面的操作不需要返回一个流而要对值做一些处理时调用,传入一个方法

Optional.<List<User>>of(userList).ifPresent(users -> users.stream().filter(user -> user.getAge() > 20).count());

ifPresentOrElse:对于下一步的操作不需要返回一个流而要对值做一些处理时调用,有值情况用一个方法处理,无值情况也用一个方法处理(要传入两个方法操作Optional中的对象)

S7-1200 数据日志 数据日志文件按照标准 CSV 格式存储在 S7-1200 CPU 装载存储器或 S7-1200 SIMATIC 存储卡中。分别可通过 PLC Web 服务器或将数据文件传送到 PC 进行管理、查看。 一、测试目的: 下面以数据日志文件存储在 S7-1200 CPU 装载存储器中,使用PLC Web 服务器进行管理为例,实现下述功能: (1)执行“DataLogging”指令将产品型号“Type”,长度“Length”,宽度“Width”三个变量值写入到数据日志文件; (2)当写入的条数达到设定的3条 阅读详情

相关推荐

竞赛无人机模块化开发实战:2023 TI电赛G题空地协同消防系统(飞控与视觉融合篇)

本文以2023年TI电赛G题为例,详细阐述了采用模块化开发思维构建空地协同智能消防系统的实战方法。文章重点拆解了无人机飞控二次开发、视觉识别与融合控制等核心模块,提供了硬件选型、代码实现与系统联调的完整指南,旨在帮助参赛者通过“搭积木”式编程高效完成复杂系统集成。

js777的博客 454

lambda表达式介绍 ---- 函数式编程

lambda表达式是Java8的一个新特性,可以我们的代码编程;从本质上来说,lambda表达式是一个,使用它能简化我们对接口代码的实现;

ggjklncffd的博客 743

PID算法(位置式pid算法和增量式pid算法)

PID 算法是闭环控制系统中常用的算法,PID 分别是 Proportion(比例)、Integral(积分)、Differential(微分)的首字母缩写。它是一种结合比例、积分和微分三个环节于一体的闭环控。

m0_57678852的博客 2万+

Java8新特性【函数式编程API、新时间日期处理API、Optional容器类】总结

文章目录1、Lambda表达式1.1什么是Lambda表达式1.2从匿名类到 Lambda 的转换1.3Lambda表达式语法2、函数式接口2.1什么是函数式接口2.2自定义函数式接口2.3内置核心函数式接口2.4接口中常用的默认方法3、方法引用与构造器引用3.1 推荐用法3.2 基本格式3.3 语法详解(了解)3.3.1引用类的静态方法3.3.2 引用对象的实例方法3.3.4 引用类的实例方法3.3.5 构造器引用4、Stream API4.1什么是Stream4.2Stream操作的三个步骤4.2.1创

欢迎来到编程小栈 1535

逆向工程Python爬虫——国税局发票查验平台

前言 这是一篇含金量很高的干货文章,笔者将手把手带领各位一步一步地实现爬取国家税务总局全国增值税发票查验平台(以下简称“查验平台”)。这个想法诞生在19年初,当时在做一款通过扫描二维码就可以查验发票的小程序。 当时由于笔者学艺尚浅,没办法模拟请求爬取查验平台,所以最终采用的技术方案是通过web自动化测试工具selenium控制浏览器去模拟查验步骤,即使这样,开发过程也是困难重重,不过最后笔者和伙伴们成功实现了整套流程,最后开发出的产品口袋发票夺得了包括2019微信小程序开发大赛赛区三等奖在内的多个奖项。 但

weixin_43102379的博客 1万+

✨在Windows11上安装虚拟机(VMware17.6.0)保姆级教程(附安装包)

VMware Workstation Pro 是一款功能强大的虚拟机软件,它允许你在单一的物理机上运行多个操作系统。性能卓越:VMware以其出色的性能和稳定性而闻名,适合运行资源密集型的虚拟机。用户友好:直观的用户界面使得即使是初学者也能快速上手。功能全面:支持多种操作系统,包括Windows、Linux、macOS等,满足不同用户的需求。企业级支持:VMware提供全面的技术支持,适合企业级用户。恭喜你成功安装了VMware Workstation Pro 17.6.0!

Python老吕的博客 1万+

java 中closed_Java中的IntStream rangeClosed()方法

的rangeClosed()在IntStream类返回类顺序排列IntStream从startInclusive到endInclusive通过的1递增步长这既包括startInclusive和endInclusive值。语法如下staticIntStreamrangeClosed(intstartInclusive,intendInclusive)在此,startInclusive是包括...

weixin_35632603的博客 1703

YOLOv13添加WDBB模块,map提升5.34!!,召回率提升6.55,准确率提升3.23

本文提出了一种基于YOLOv13改进的目标检测模型,通过引入WDBB模块显著提升了检测性能。实验结果表明,添加WDBB模块后,mAP提升11.34,召回率提升14.55,准确率提升3.23。文章详细介绍了模型移植方法,包括创建新的yaml配置文件、修改tasks.py和__init__.py文件,以及实现rep_block.py中的核心转换函数。改进后的模型通过深度卷积、通道注意力等模块优化了特征提取能力,同时保持了轻量化的特点。该工作为YOLO系列模型的性能提升提供了新的思路和技术实现。

FJN110的博客 2624

java8 新特性之 Stream()的使用。

Stream 流的使用   1,Stream 常用的 Api        1.1  筛选和切片:               List&lt;String&gt; excapleStrs = Arrays.asList("java", "java", "javaScript", "php","python","ios", "go");   

DavinQi的博客 3260

uniapp(微信小程序) - 实现uniapp小程序电子签名板,横屏手写姓名签名专用写字画板,客户专用签字板,手写签名签字画板组件,手写签名,(详细运行示例,一键复制开箱即用)

uniapp实现微信小程序的电子签名效果,uniapp微信小程序 电子签名 写字板,用uniapp实现微信小程序的电子签名,uniapp微信小程序canvans实现手写签名,记录一个uniapp写的小程序的手写板,横屏,用于签名,unniapp实现电子签名,uniapp怎么做横屏的手写签名,uniapp如何实现签字板,uniapp小程序平台下怎么做电子签名板组件,uniapp电子签名插件,uniapp最好用的电子写字板插件组件源码,实现uniapp 手写签名功能,手写板、签字板,uni-app插件市场最好的

✅ 精选推荐文章 1万+

java项目反编译工具记录,共计6个工具

java项目反编译工具记录,共计6个工具

橙-极纪元-JJYCheng 1801

Java函数式编程和Lambda表达式

文章目录什么是函数式编程Lambda表达式@FunctionalInterface函数式接口Lambda表达式的格式方法引用 什么是函数式编程 相信大家都使用过面向对象的编程语言,面向对象编程是对数据进 行抽象,而函数式编程是对行为进行抽象。函数式编程让程序员能够写出更加容易阅读的代码。那什么时候函数式编程呢? 函数式编程是一种编程的方法论,主要是将行为编写成一个个的函数。 什么是函数? 函数就是...

程序那些事 1万+

机器人动力学仿真软件:PyBullet_(10).案例分析:双足机器人行走仿真

在本节中,我们将详细探讨如何使用PyBullet进行双足机器人的行走仿真。双足机器人行走仿真是一个复杂的动力学问题,涉及多个关节的协调运动和环境交互。通过本节的学习,您将了解如何创建和控制双足机器人模型,设置仿真环境,以及实现基本的行走算法。首先,我们需要创建一个双足机器人模型。PyBullet支持多种模型格式,包括URDF(Unified Robot Description Format)和MJCF(MuJoCo XML Format)。URDF是一种广泛使用的机器人模型描述格式,我们将使用URDF来创建

kkchenjj的博客 913

Lambda 表达式和函数式编程

Lambda表达式是一种轻量级的匿名函数,它可以被看作是一种简洁的方式来表示单一方法的接口(Single Abstract Method,SAM)。Stream API是Java 8中引入的用于处理集合数据的函数式编程的工具。它允许你以声明性的方式处理数据集合,支持各种操作,如映射、过滤、归约等。Lambda表达式和函数式编程是Java 8引入的两个重要特性,为Java带来了更加灵活和简洁的编程方式。函数式接口是只包含一个抽象方法的接口。包,其中包含了一些常用的函数式接口,如。

xinyi_java的博客 797

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

函数式编程和lambda表达式

一.接口的默认方法 (1)在接口中添加一个非抽象方法只需要使用一个default 关键字就可以 (2)我们把非抽象方法理解成一个扩展方法, 二.函数式编程 1.什么是函数式编程 ?一切皆函数 2.将处理问题的粒度从类变成函数,从而可以更好的满足系统对重用性,和扩展性的支持 3.可以将函数作为参数传递给另一个函数 4.可以简化代码的操作 5.开发速度快,易于并发编程,不需要考虑死锁 6.耗费cpu 三.Lambda表达式 (1)lambda表达式是一种新的语法形式,简化了代码的开发操作,由编译器转化为常规的代

weixin_45701447的博客 468

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Java8函数式编程和lambda表达式

文章目录函数式编程JDK8接口新特性函数接口方法引用 函数式编程 函数式编程更多时候是一种编程的思维方式,是一种方法论。函数式与命令式编程区别主要在于:函数式编程是告诉代码你要做什么,而命令式编程则是告诉代码要怎么做。简单说,函数式编程是基于某种语法或调用API去进行编程。 例如,从整型数组中找出最小的那个数字,采用命令式编程实现如下: public static void main(String...

FEEL的博客 3241

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Java8 Lambda表达式 和 函数式编程 原理详解

前言 1、前言   Java8既JDK1.8。Lambda表达式是Java8的新特性,除此之外Java8还提供了其他新特性,比如:函数式编程、方法引用、Stream、Optional类、默认方法、新的日期类型、Base64、Nashorn, JavaScript 引擎。   本篇详细介绍Lambda表达式,其他的后续慢慢介绍。   它是一个语法糖,糖是甜的,但是对于初学者并不是,当你熟悉之后,你会发现,它是真的香。   Lambda表达式的初衷是,进一步简化匿名类的语法(不过实现上,Lambda表达

Curry4ever 2757

用通俗易懂的大白话搞明白Java里的函数式编程和Lambda表达式

今天,用通俗易懂的大白话来搞明白Java里的函数式编程和Lambda表达式

曹举的个人博客 5697

Java 函数式编程和 lambda 表达式

为什么要使用函数式编程 函数式编程更多时候是一种编程的思维方式,是种方法论。函数式与命令式编程的区别主要在于:函数式编程是告诉代码你要做什么,而命令式编程则是告诉代码要怎么做。说白了,函数式编程是基于某种语法或调用API去进行编程。例如,我们现在需要从一组数字中,找出最小的那个数字,若使用用命令式编程实现这个需求的话,那么所编写的代码如下: publicstati...

测试 354

Lambda表达式三:函数式编程一:函数式编程简介;Predicate函数式接口简介和应用;

本篇博客介绍了:函数式编程,Lambda表达式,函数式接口;然后,介绍了Predicate这个函数式接口; 目录 1.核心概念简述 (1)函数式编程:=Lambda+函数式接口 (2)Lambda表达式,在上篇博客中已经介绍了。 (3)函数式接口 二.案例 (1)Predicate接口:引子 (2)操作案例对比: 首先,采用传统的方式:有点笨重 采用函数式编程的方式:很给力 1.核心概念简述 (1)函数式编程:=Lambda+函数式接口 函数式编程=Lambda表达式+函数式...

小枯林的博客 607

Java 8 函数式编程:Lambda 表达式和方法引用

背景 在很多其他语言中,函数是一等公民。例如 JavaScript 中,函数(Function)和字符串(String)、数字(Number)、对象(Object)等一样是一种数据类型。可以这样定义函数: var myFunction = function () { doSomething(); }; 也可以将函数作为参数: setTimeout(function() { do...

叉叉哥的BLOG 2638

为什么要用Lambda表达式和函数式编程?

为什么要用Lambda表达式和函数式编程?

m0_62588361的博客 275

浅谈Java lambda表达式和函数式编程

浅谈Java lambda表达式和函数式编程什么是Java lambda表达式?函数式编程是啥?lambda表达式是函数式编程的一种吗?

菜菜bu菜的博客 2327
下一篇: Redis底层数据结构、键值存储原理、哈希冲突解决方式、各种数据类型操作时间复杂度
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值