1.接口默认方法(Default Methods for Interfaces)
- Java 8能够通过使用
default
关键字向接口添加非抽象方法实现,此功能成为虚拟扩展方法1
2
3
4
5
6interface Formula{
double calculate(int a);
default double sqrt(int a){
return Math.sqrt(a);
}
}
- Formula接口中除了抽象方法计算接口公式还定义了默认方法
sqrt
。实现该接口的类只需要实现抽象方法calculate
。默认方法sqrt
可以直接使用。1
2
3
4
5
6
7
8
9
10
11
12public class Main{
public static void main(String[] args){
Formula formula = new Formula(){
@Override
public double calculate(int a){
return sqrt(a * 100);
}
};
System.out.println(formula.calculate(100));
System.out.println(formula.sqrt(100));
}
}
2.lambda表达式(lambda expressions)
1 | List<String> names = Arrays.asList("peter", "anna", "mike", "xenis"); |
Lambda表达式写法1
2
3Collections.sort(names, (String a, String b) -> {
return b.compareTo(a);
});
1 | Collections.sort(names, (String a, String b) -> b.compareTo(a)); |
1 | names.sort((a, b) -> b.compareTo(a)); |
3. 函数式接口
- 函数式接口值仅仅只包含一个抽象方法,但可以有多个非抽象方法(默认方法)的接口。
- 可以隐式转换成lambda表达式,java.lang.Runnable, java.util.concurrent.Callable。
- @FunctionalIterface
- 只要接口包含一个抽象方法,虚拟机会自动判断该接口为函数式接口。
1
2
3
4@FunctionalInterface
public interface Converter<F, T>{
T convert(F form);
}
1 | // 将数字类型转成整数类型 |
Java8允许通过:: 关键字传递方法或构造函数的引用。
1
2
3
4
5
6
7
8
9
10// 对象引用
class Something {
String startWith(String s){
return String.valueOf(s.charAt(0));
}
}
Something something = new Something();
Converter<String, String> converter = something::startWith;
String converted = converter.convert("Java"); // "J"构造函数使用::关键字来引用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20class Person {
String firstName;
String lastName;
Person(){}
Person(String firstName, String lastName){
this.firstName = firstName;
this.lastName = lastName;
}
}
// 指定一个用来创建Person对象的对象工厂接口
interface PersonFactory<P extends Persion>{
P create(String firstName, String lastName);
}
// 使用构造函数引用来讲他们关联起来
PersonFactory<Person> personFactory = Person::new; // 这里使用Person:new来获取Person类构造函数的引用
Person person = personFactory.create("Peter", "Parker");Lambda表达式作用域
访问局部变量
1
2
3
4
5// final int num = 1;
int num = 1; // 可以不用final修饰,但是后面不能修改num
Converter<Integer, String> stringConverter = (form) -> String.valueOf(form + num);
stringConverter.convert(2); // 3访问字段和静态变量: 对lambda表达式中的实例字段和静态变量都有读写访问权限,和匿名对象一致。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class Lambda4 {
static int outerStaticNum;
int outerNum;
void testScopes() {
Converter<Integer, String> stringConverter1 = (from) -> {
outerNum = 23;
return String.valueOf(from);
};
Converter<Integer, String> stringConverter2 = (from) -> {
outerStaticNum = 72;
return String.valueOf(from);
};
}
}方位默认接口方法: 无法从lambda表达中访问默认方法。
5.内置函数式接口
JDK1.8中包含了许多内置函数式接口
- Predicates:只有一个参数的返回Boolean类型值的断言型接口。该接口包含许多默认方法将Predicate组合成其他复杂逻辑(与或非)
- Optionals:用户防止NullPointerException的工具
6.Streams流
- java.util.Stream 表示能应用在一组元素上一次执行的操作序列。
- Stream 操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,这样你就可以将多个操作依次串起来。Stream 的创建需要指定一个数据源,比如 java.util.Collection 的子类,List 或者 Set, Map 不支持。Stream 的操作可以串行执行或者并行执行
过滤Filter
- 过滤通过一个predicate接口来过滤并只保留符合条件的元素,该操作属于中间操作,所以我们可以在过滤后的结果来应用其他Stream操作(比如forEach)。forEach需要一个函数来对过滤后的元素依次执行。forEach是一个最终操作,所以我们不能在forEach之后来执行其他Stream操作
1
2
3
4stringList.stream()
.filter((s) -> s.startWith('a'))
.forEach(System.out::println);
// forEach 是为 Lambda 而设计的,保持了最紧凑的风格
- 过滤通过一个predicate接口来过滤并只保留符合条件的元素,该操作属于中间操作,所以我们可以在过滤后的结果来应用其他Stream操作(比如forEach)。forEach需要一个函数来对过滤后的元素依次执行。forEach是一个最终操作,所以我们不能在forEach之后来执行其他Stream操作
Sorted(排序)
- 排序是一个中间操作,返回排序后的Stream
- 排序只创建一个排列好的Stream,而不影响原有的数据源,排序之后原数据stringCollection不会被修改。
1
2
3
4
5
6
7stringList.stream()
.sorted()
.filter((s) -> s.startsWith("a"))
.forEach(System.out::println);
```
+ Map(映射)
- 中间操作map会将元素根据指定的Function接口来一次将元素转成另外的对象。
stringList.stream()
.map(String::toUpperCase)
.sorted((a, b) -> b.compareTo(a))
.forEach(System.out::println);1
2+ Match(匹配)
- Stream提供的匹配操作,允许检测指定的Predicate是否匹配整个Stream。所有的匹配操作都是最终操作,返回Boolean。
boolean anyStartsWithA = stringList.stream()
.anyMath((s)->s.startsWith(“a”)); // True1
2+ Count(计数)
- 计数是一个最终操作,返回stream中元素的个数,返回类型是long。
long startsWithB = stringList.stream()
.filter((s) -> s.startsWith(“b”))
.count();1
2+ Reduce(规约)
- 最终操作,允许通过指定的函数来将stream中的对各元素规约为一个元素。
Optional
.sorted()
.reduce((s1, s2) -> s1 + “#” + s2);
reduced.ifPresent(System.out::println);//aaa1#aaa2#bbb1#bbb2#bbb3#ccc#ddd1#ddd2`
- Parallel Streams(并行流)
- Sequential Sort(串行排序)
- Parallel Sort(并行排序)
- Maps
- Date API
- Annotations(注解)