Java 8 新特性综合概述

本文深入探讨Java 8的革命性改进,包括函数式接口、Lambda表达式、方法引用和Stream流等特性,详细阐述了这些新特性对代码编写的重大影响,并通过实例展示了如何利用这些特性简化代码,提高表达能力和简洁性。

 根据Oracle 对java 8开发进度安排,java将于2014年的3月份发布。从java8 新引入的特性看,函数式编程语言对java8 影响很大,运行在JVM上的ScalaGroovy等编程语言部分特性被java 8吸收。平台、API等方面先不关注,仅就从编程语言特性来说java8绝对是一次革命性的的改进,有了java 8 java语言的表达能力、简洁性有了很大提高,跟Scala groovy等JVM上的新兴语言差距缩小了很多。语言特性改进概括起来有以下几点

  •  函数式接口  
  •  Lambda表达式
  • 方法引用
  • 接口的改进
  • Stream
这篇文章我将说说以上几个语言特性,以及对代码编写的影响

一  函数式接口

 所谓函数式接口(FunctionalInterface)是指只有一个抽象方法的接口,比如java 8 之前的Runnabe接口(只有run方法),Comparator接口(comare方法),Comparable(compareTo方法)都属于函数式接口,到了Java 8时代这些接口都被注解为@FunctionalInterface,另外@FunctionalInterface也是java 8 新进入的注解,Java 8新增了一个包java.util.function,在function包下提供了大量常见函数式接口,举例如一下几个

Predicate:谓词,boolean test(T t) 输入类型T,输出布尔值

Supplier 生产者,T  get(),无输入,输出类型T

Consumerer 消息者,void accept(T t),输入T,无输出

Function 函数,R apply(T t ) ,输入T 输出R

 

 二 Lambda

Lambda表达式就是匿名方法,方法可以通过名称被重用,而匿名方法不能在被其它代码所调用。lambda也具有输入参数,方法体,返回值,比如(Object o) ->{System.out.println(o.toString()); return o.toSting();}输入参数为Object o 返回值为String类型,方法体为{}之间的语言

比如方法sum方法

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

 改用lambda表达式为

(int x, int y) -> {return x + y;}

 在特点场景下通过java 8 类型推导功能,可以省略lambda输入参数的类型,比如上面的sum方法lambda表达式可以改写为

(x, y) -> {return x + y;}

 lambda表达式方法体内可以访问lamba外的变量,相比匿名内部类访问外部类变量需要final修饰方便多了

 Runnable的run方法没有输入参数,用lambda表达式写Runnable接口实现类可以这样写

   

Runable r = () -> {System.out.println("Hello");}

 

Comparator<String>接口实现类可以这样写

Comparator comparator = (String str1,String str2) ->{return s1.compareToIgnoreCase(s2);}
//由于lambda基于类型推导功能,可以省去str1和str2前面的类型String
Comparator comparator = (str1,str2) ->{return s1.compareToIgnoreCase(s2);}

 

 

三 方法引用

  通过方法引用轻轻松松的实现function as first-classs object(函数作为一类对象)功能,可以将方法作为变量看待,作为参数传递。方法引用符号是::

比如通过 方法引用实现字符串从小写到大写的转换

Function<String, String> upperfier = String::toUpperCase;
 System.out.println(upperfier.apply("Hello"));

 比如Set类里有boolean contains(T t)方法,显然方法属于谓词(Predicate)函数,我用可以这用的使用Set的contains方法

 

 Set<String> knowNames = new HashSet<>();
 knowNames.add("Zhang");
 knowNames.contains("Zhang");

 Predicate<String> isKnowName = knowNames::contains;
 isKnowName.test("Zhang");
 isKnowName.test("Li");

 

以上举的方法引用都是实例方法引用,方法引用包括(此处方法包括静态方法、实例方法、构造方法、数组构造方法) 

 

  四 接口的改进

  java 8 中对接口的功能做了改进,包括默认方法和静态方法。

 

 1 默认方法

在java8以前接口不能定义具体方法,只能定义抽象方法。作为一个通用的库或框架,接口一旦发布之后不能轻易的增加新的抽象方法,否则该接口的具体实现类都必须跟着实现新增的方法。java 8 中为了不破坏接口的实现,允许接口有具体的实现方法,实现方法用关键字default修饰 也叫默认方法。

比如JDK中Iterable接口中新增的默认方法 forEach实现遍历功能

 

 default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

 

 

接口增加了默认方法之后就会存在多继承问题。

  比如接口1和接口2都有相同的默认方法method1,接口3同时继承了接口1和接口2,在接口3以及接口3的实现类里 method1到底是继承接口1还是继承接口2的method1方法呢? java 8 通过引入新的语法来i解决问题,接口3必须重写method1方法,在method1方法里可以指定到底是继承接口1还是接口2,比如下面的代码DrawInteface3的draw必须显示指定继承哪个父接口的方法

 

public interface DrawInterface1 {

    default void draw(){
        System.out.println("DrawInterface1.draw");
    }
}

public interface DrawInterface2 {

    default void draw(){
        System.out.println("DrawInterface2.draw");
    }
}

public interface DrawInterface3 extends DrawInterface1,DrawInterface2 {
    default void draw(){
        //接口名.super.父接口方法名 来指定调用哪个接口方法
        DrawInterface1.super.draw();
    }
}
 
  2 静态方法

  在java 8 以前接口标准库里定义了Collection接口,然后增加一个Collections工具了辅助Collection接口,java 8 里允许定义接口的静态方法(static修饰)

   比如Comparator接口增加了大量的静态放,有了comparing这个静态方法后写比较器非常的轻松

 

public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor)
    {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
    }

//根据名字做比较的比较器
Comparator nameComparator = Comparator.comparing(Employee::getName);

//根据薪水做比较比较器
Comparator salaryComparator = Comparator.comparing(Employee::getSalary);
 

 

 五  Stream 流

1 本质

java8 新增的Stream非之前IO相关的流,Stream的本质是对数据源进行抽象提供一套通用API,引入Stream、函数式接口、lambda等几大特性候java 8 有了一些函数式编程语言味道

Stream实现map filter reduce等操作,Stream的数据源包括数组、集合、IO通道、随机数生成器等,Stream相关接口在java.util.stream包下

 

2 使用例子

现在举个List<Integer>来说明Stream的filter map reduce等常见高阶函数的使用   

//对list求和 
int result = list.stream().reduce(0,(x,y) -> x + y);

//对list过滤(大于5的数字)再求和 
int result = list.stream().filter(x -> x > 5).reduce(0,(x,y) -> x + y);

//对list 过滤(大于5的数字) 映射(求平方) 再求和,先通过mapToInt生成IntStream,调用sum方法 
result = list.stream().filter(x -> x > 5).map(x -> x * x).mapToInt(x -> x).sum();
 filter参数为谓词Predicate<T>   predicate,map函数参数为Function<T,R> mapper ,reduce参数为(T identity,BinaryOperator<T> accumulator),identity为起始值,accumulator为二元操作函数。
   x -> x > 5为Predicate的lambda写法,(x , y ) -> x + y 为BinaryOperator<T> accumulator的lambda写法

 

3 Stream的实际应用

当年学习Oracle时入门的例子就用employee表,这里我举例还是用Employee,只是从数据库表换成里java类。现有一个List<Employee> employees (Employee包括name、salary、departId三个属性),通过Stream的相应方法实现一些常见的"统计功能"

 

//求所有员工薪资总和
        int totalSalary = employees.stream()
                .map(e -> e.getSalary())
                .reduce(0,(x,y) -> x + y);
        System.out.println("totalSalary = " + totalSalary);
 
 //所有雇员姓名
 List<String> nameList = employees.stream()
                .map(e -> e.getName())
                .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
 System.out.println("nameList = " + nameList);
 

 

 

//求平均工资
double averageSalary = employees.stream()
                .mapToInt(e -> e.getSalary())
                .average()
                .getAsDouble();

 

 //求平均工资,用Collectors工具类的帮助方法
averageSalary = employees.stream()
                .collect(Collectors.averagingInt(e -> e.getSalary()));
  System.out.println("averageSalary = " + averageSalary);

 

 //雇员按照部门分组
 Map<Integer,List<Employee>> deaprtEmployee = employees.stream()
                .collect(Collectors.groupingBy(e -> e.getDepartId()));

 

 //打印每个部门的平均工资
        deaprtEmployee.forEach((k,v) -> System.out.println(k+":" + v.stream().mapToInt(
                e -> e.getSalary()).average().getAsDouble()));

 

//查找每个部门工资最低的雇员
deaprtEmployee.forEach((k,v) -> System.out.println(k+":" + v.stream().
                sorted(Comparator.comparing(Employee::getSalary)).findFirst().get()));

 

 //对雇员根据名字排序
employees.sort(Comparator.comparing(Employee::getName));

 

通过以上的例子可以看出java 8 的表达能力有了很大提高,更少的代码能完成更多的事情。另外通过Stream的collect()方法和工具类Collectors可以轻轻松松实现很多运算方法。

 

 

 

 

 

本项目采用C++编程语言结合ROS框架构建了完整的双机械臂控制系统,实现了Gazebo仿真环境下的协同运动模拟,并完成了两台实体UR10工业机器人的联动控制。该毕业设计在答辩环节获得98分的优异成绩,所有程序代码均通过系统性调试验证,保证可直接部署运行。 系统架构包含三个核心模块:基于ROS通信架构的双臂协调控制器、Gazebo物理引擎下的动力学仿真环境、以及真实UR10机器人的硬件接口层。在仿真验证阶段,开发了双臂碰撞检测算法和轨迹规划模块,通过ROS控制包实现了末端执行器的同步轨迹跟踪。硬件集成方面,建立了基于TCP/IP协议的实时通信链路,解决了双机数据同步和运动指令分发等关键技术问题。 本资源适用于自动化、机械电子、人工智能等专业方向的课程实践,可作为高年级课程设计、毕业课题的重要参考案例。系统采用模块化设计理念,控制核心与硬件接口分离架构便于功能扩展,具备工程实践能力的学习者可在现有框架基础上进行二次开发,例如集成视觉感知模块或优化运动规划算法。 项目文档详细记录了环境配置流程、参数调试方法和实验验证数据,特别说明了双机协同作业时的时序同步解决方案。所有功能模块均提供完整的API接口说明,便于使用者快速理解系统架构并进行定制化修改。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
【微电网】【创新点】基于非支配排序的蜣螂优化算法NSDBO求解微电网多目标优化调度研究(Matlab代码实现)内容概要:本文围绕基于非支配排序的蜣螂优化算法(NSDBO)在微电网多目标优化调度中的应用展开研究,提出了一种改进的智能优化算法以解决微电网系统中经济性、环保性和能源效率等多重目标之间的权衡问题。通过引入非支配排序机制,NSDBO能够有效处理多目标优化中的帕累托前沿搜索,提升解的多样性和收敛性,并结合Matlab代码实现仿真验证,展示了该算法在微电网调度中的优越性能和实际可行性。研究涵盖了微电网典型结构建模、目标函数构建及约束条件处理,实现了对风、光、储能及传统机组的协同优化调度。; 适合人群:具备一定电力系统基础知识和Matlab编程能力的研究生、科研人员及从事微电网、智能优化算法应用的工程技术人员;熟悉优化算法与能源系统调度的高年级本科生亦可参考。; 使用场景及目标:①应用于微电网多目标优化调度问题的研究与仿真,如成本最小化、碳排放最低与供电可靠性最高之间的平衡;②为新型智能优化算法(如蜣螂优化算法及其改进版本)的设计与验证提供实践案例,推动其在能源系统中的推广应用;③服务于学术论文复现、课题研究或毕业设计中的算法对比与性能测试。; 阅读建议:建议读者结合文中提供的Matlab代码进行实践操作,重点关注NSDBO算法的核心实现步骤与微电网模型的构建逻辑,同时可对比其他多目标算法(如NSGA-II、MOPSO)以深入理解其优势与局限,进一步开展算法改进或应用场景拓展。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值