0%

浅谈java8

天上乌飞兔走,人间古往今来。万般回忆化尘埃,只有青山不改。

一、java历史及发展

起源:

  • 1995年5月23日,Java语言正式诞生。

  • 1996年1月,第一个JDK-JDK1.0诞生。

    • Sun Classic VM(虚拟机)
    • Applet(java小应用程序)
    • AWT(java图形设计)
  • 1996年4月,10个最主要的操作系统供应商申明将在其产品中嵌入Java技术。

  • 1996年9月,约8.3万个网页应用了Java技术来制作。

  • 1997年2月18日,JDK1.1发布。 

    • JAR(jar包)
    • JDBC(Java DataBase Connectivity)(连接数据库)
    • JavaBeans(java规范)
    • RMI(远程调用)
    • Inner Class(内部类)
    • Reflection(反射)
  • 1997年4月2日,JavaOne会议召开,参与者超过万人,创造当时全球同类会议规模之纪录。

  • 1997年9月,JavaDeveloperConnection社区成员超过十万。

  • 1998年2月,JDK1.1被下载超过2,000,000次。

  • 1998年12月8,Java的企业平台Java EE正式发布。

  • 1999年6月,Sun公司发布Java的三大版本:标准版(Java SE)、企业版(Java EE)、微型版(Java ME)。

  • 2000年5月8日,JDK1.3发布。

    • 数学运算
    • Timer API(时间)
    • Java Sound API(声音)
    • CORBA IIOP实现RMI的通信协议
    • Java 2D新特性
    • jar文件索引
  • 2000年5月29日,JDK1.4发布。

  • 2001年6月5日,NOKIA宣布,到2003年将出售1亿部支持Java的手机。

  • 2001年9月24日,Java EE 1.3发布。

  • 2002年2月26日,J2SE1.4发布,自此Java的计算能力有了大幅提升。

  • 2004年9月30日,J2SE1.5发布,是Java语言发展史上的又一里程碑事件。为了表示这个版本的重要性,Java SE 1.5正式更名为Java SE 5.0。

    • 自动装箱拆箱
    • 泛型
    • 元数据
    • Introspector(内省)
    • enum(枚举)
    • 静态引入
    • 可变长参数(Varargs)
    • foreach(高级虚幻)
    • JMM(内存模型)
    • concurrent(并发包)
  • 2006年12月,Sun公司发布了JDK1.6(也被称为Java SE 6)。一直以来,Sun公司维持着大约2年发布一次JDK新版本的习惯。

  • 2009年4月20日,Oracle宣布将以每股9.5美元的价格收购Sun,该交易的总价值约为74亿美元。但Oracle通过收购Sun公司获得了两项软件资产:Java和Solaris。2007年11月,Java语言作为服务器端编程语言,已经取得了极大地成功;而Android平台的流行,则让Java语言获得了在客户端程序上大展拳脚的机会。

  • 2011年7月28日,Oracle公司发布了Java SE 7,这次版本升级经过了将近5年时间。Java SE 7也是Oracle发布的第一个Java版本,引入了二进制整数、支持字符串的switch语句、多异常捕捉、自动关闭资源的try语句等新特性。

  • 2014年3月18日,Oracle公司发布了Java SE 8,这次版本升级为Java带来了全新的Lambda表达式。除此之外,Java 8还增加了大量新特性,这些新特性使得Java变得更加强大。

    • Lambda表达式
    • 函数式接口
    • 方法引用和构造器调用
    • Stream API
    • 接口中的默认方法和静态方法
    • 新时间日期API
  • …    

二、Lambda表达式(来源于C#和Scala语言)

1、概念

可以把Lambda表达式理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。

  • 匿名——我们说匿名,是因为它不像普通的方法那样有一个明确的名称:写得少而想得多!

  • 函数——我们说它是函数,是因为Lambda函数不像方法那样属于某个特定的类。但和方法一样,Lambda有参数列表、函数主体、返回类型,还可能有可以抛出的异常列表。

  • 传递——Lambda表达式可以作为参数传递给方法或存储在变量中。

  • 简洁——无需像匿名类那样写很多模板代码。

2、组成

  • 参数列表
  • 箭头
  • Lambda主体

2.1 例子说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//第一个Lambda表达式具有一个String类型的参数并返回一个int。Lambda没有return语句,因为已经隐含了return
(String s) -> s.length() ;

/**
* 第二个Lambda表达式有一个Apple 类型的参数并返回一个boolean(苹果的重量是否超过150克)
*/
(Apple a) -> a.getWeight() > 150;

/**
* 第三个Lambda表达式具有两个int类型的参数而没有返回值(void返回)。注意Lambda表达式可以包含多行语句,这里 *是两行.
*/
(int x, int y) -> {
System.out.println("Result:");
System.out.println(x+y);
}

/**
* 第四个Lambda表达式没有参数,返回一个int
*/
() -> 42 ;

/**
* 第五个Lambda表达式具有两个Apple类型的参数,返回一个int:比较两个Apple的重量
*/
(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());

// 解答
答案:只有45是无效的Lambda。
(1) 这个Lambda没有参数,并返回void。它类似于主体为空的方法:public void run() {}。
(2) 这个Lambda没有参数,并返回String作为表达式。
(3) 这个Lambda没有参数,并返回String(利用显式返回语句)。
(4) return是一个控制流语句。要使此Lambda有效,需要使花括号,如下所示:
(Integer i) -> {return "Alan" + i;}。
(5)“Iron Man”是一个表达式,不是一个语句。要使此Lambda有效,你可以去除花括号和分号,如下所示:(String s) -> "Iron Man"。或者如果你喜欢,可以使用显式返回语
句,如下所示:(String s)->{return "IronMan";}。

2.2 小试牛刀

根据上述语法规则,以下哪个不是有效的Lambda表达式?

(1) () -> {}

(2) () -> “Raoul”

(3) () -> {return “Mario”;}

(4) (Integer i) -> return “Alan” + i;

(5) (String s) -> {“IronMan”;}

3.函数式接口

含义:接口中只有一个抽象方法。

Lambda表达式需要函数式接口的支持,可以通过在接口上方添加@FunctionInterface来判断接口是否是函数式接口。

jVM可以通过上下文推断出参数类型,“类型推断”。

三、java8内置四大函数式接口

1、Consumer:消费型接口

2、Supplier:供给型接口

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

4、Predicate:断言型接口

四、Stream流

1、引入

案例:实体Food,属性有热量值calories和食物名称name,现有一食物集合foodList,实现返回低热量的菜肴名称的,并按照卡路里排序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 传统实现(非java8)
List<Dish> lowCaloricDishes = new ArrayList<>();
for(Dish d: foodList){
if(d.getCalories() < 400){
lowCaloricDishes.add(d);
}
}
Collections.sort(lowCaloricDishes, new Comparator<Dish>() {
public int compare(Dish d1, Dish d2){
return Integer.compare(d1.getCalories(), d2.getCalories());
}
});
List<String> lowCaloricDishesName = new ArrayList<>();
for(Dish d: lowCaloricDishes){
lowCaloricDishesName.add(d.getName());
}

// Java8实现
List<String> lowCaloricDishesName =
foodList.stream()
.filter(d -> d.getCalories() < 400)
.sorted(comparing(Dish::getCalories))
.map(Dish::getName)
.collect(toList());

2、使用

  • 筛选(filter)、切片(limit)和匹配
  • 流的扁平化flatMap
  • 归约
    • 获取最值
    • 求和

3、查找与匹配

4、归约与收集

四、Optional