根据Oracle 对java 8开发进度安排,java将于2014年的3月份发布。从java8 新引入的特性看,函数式编程语言对java8 影响很大,运行在JVM上的Scala、Groovy等编程语言部分特性被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可以轻轻松松实现很多运算方法。
分享到:
相关推荐
它引入了许多新特性,如Lambda表达式、流(Stream)API、日期和时间API等,这些特性极大地提高了Java语言的功能性和编程效率。Java 8的这些改进使得它成为Java开发者们广泛使用的版本之一。 #### 32位与64位JDK的区别...
### JAVA综合实验报告知识点 #### 实验背景与目标 ...通过本次实验,不仅能够锻炼学生的编程技能,还能帮助他们更好地理解面向对象编程的思想和Java语言的特性,为将来更复杂的项目打下坚实的基础。
随着技术的演进,Java持续发展,例如Java JDK 6引入的新功能,进一步提升了开发效率和性能。 学习Java,需要端正态度,保持勤奋,通过多看、多练、多问和多想来不断提升技能。同时,了解并掌握Java的基本概念、开发...
Java入门笔记文档详细阐述了Java编程语言的基本概念、开发工具、编程基础、面向对象编程、多线程、集合框架、IO流、网络编程、安全加密、反射机制、新特性、内存管理等多个方面,为初学者提供了一条通往Java编程世界...
这只是一个基本的Java技术面试的概述,实际面试中可能会涉及到更多Java语言特性和框架、设计模式、并发编程、集合框架、IO/NIO、网络编程、数据库连接池、Spring Boot、MyBatis等知识点。全面掌握这些内容将大大增加...
Java 6相较于Java 5,主要改进了性能和开发者体验,而后续的Java 7和8则带来了更多突破性变化,如Lambda表达式、模块系统(Project Jigsaw)以及G1垃圾收集器等。 总结,Java JDK6作为Java发展历程中的一个重要里程...
- **初始化顺序**: 在Java中,当创建一个类的新实例时,会先初始化类中的静态成员,然后才是实例成员的初始化。 - **案例分析**: 如课本中的`StaticInitialization.java`程序所示,类`Table`和`Cupboard`都有静态...
Java 综合面试资料集 Java 基础知识点: 1. Java 概述:Java 是一种高级的、基于对象的、面向对象的编程语言,它可以运行在多种平台上。 2. JDK、JRE 和 JVM 的关系:JDK(Java Development Kit)是 Java 开发工具...
### Java基础知识概述 #### 1. Java简介 Java是由Sun Microsystems公司于1995年推出的面向对象的...以上是对Java基础知识的综合概述,涵盖了Java语言的基础概念、核心特性和编程技巧,为初学者提供了坚实的学习起点。
2. 接口是Java 8引入的一个新特性,允许在接口中定义默认方法和静态方法。 Java Applet: 1. Java Applet是运行在支持Java的浏览器中的小程序,用于增强网页的交互性。 2. Applet通常嵌入在HTML页面中,并通过标签...
Java技术概念图是一个全面概述Java编程语言及其相关技术的综合资源。这个概念地图涵盖了Java从基础知识到高级特性的广泛领域,旨在帮助学习者理解和掌握Java技术栈的关键元素。以下是根据提供的信息提炼出的一些核心...
这份资料在原有的面试题库基础上进行了精心筛选和更新,删除了过时或无用的内容,并加入了最新的技术和深入的知识点,如Java 7的新特性,以确保面试者能接触到最实用、最具价值的信息。 **第一章 内容介绍** 这部分...
第01章 Java概述.ppt 第02章 Java语言基础.ppt 第03章 面向对象的核心特性.ppt 第04章 接口、内部类和包.ppt 第05章 异常处理.ppt 第06章 图形用户界面.ppt 第07章 多线程.ppt 第08章 Applet应用程序.ppt 第09章 ...
### Java优秀学习笔记知识点概述 #### 一、Java语言简介及特性 - **稳健性**:Java通过改进C++中的指针概念引入了引用的概念,从而增强了安全性。Java中的引用不可计算,避免了指针计算可能导致的问题。此外,Java...