Main reference:

[1] http://winterbe.com/posts/2014/03/16/java-8-tutorial/

[2] https://plus.google.com/107771575694787223844/posts

1. Add default methods for Interfaces

In java 8, Interface could have concrete methods using keyword 'default'.

interface People {
void kick(int a); default String eat(int a) {
return "Done";
}
}

2. Lambda Expressions

Before Java 8:

List<String> ages = Arrays.asList(20, 30, 40, 50);

Collections.sort(names, new Comparator<String>() {
@Override
public int compare(int a, int b) {
return b.compareTo(a);
}
});

Use Lambda:

Collections.sort(names, (a, b) -> b.compareTo(a));

3. Functional Interfaces

Each lambda corresponds to a given type, specified by an interface. A so called functional interface must contain exactly one abstract method declaration.

@FunctionalInterface
interface Converter<F, T> {
T convert(F from);
}

The code is also valid if the @FunctionalInterface annotation would be ommited.

Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
Integer converted = converter.convert("123");
System.out.println(converted); // 123

4. Method and Constructor References

The above example code can be further simplified by utilizing static method references:

Converter<String, Integer> converter = Integer::valueOf;
Integer converted = converter.convert("123");
System.out.println(converted); // 123

Java 8 enables you to pass references of methods or constructors via the :: keyword. The above example shows how to reference a static method. But we can also reference object methods:

class Something {
String startsWith(String s) {
return String.valueOf(s.charAt(0));
}
}
Something something = new Something();
Converter<String, String> converter = something::startsWith;
String converted = converter.convert("Java");
System.out.println(converted); // "J"

Let's see how the :: keyword works for constructors. First we define an example bean with different constructors:

class Person {
String firstName;
String lastName; Person() {} Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}

Next we specify a person factory interface to be used for creating new persons:

interface PersonFactory<P extends Person> {
P create(String firstName, String lastName);
}

Instead of implementing the factory manually, we glue everything together via constructor references:

PersonFactory<Person> personFactory = Person::new;   //http://www.byteslounge.com/tutorials/java-8-method-references
Person person = personFactory.create("Peter", "Parker");

We create a reference to the Person constructor via Person::new. The Java compiler automatically chooses the right constructor by matching the signature of PersonFactory.create.

5. Lambda Scopes

Accessing outer scope variables from lambda expressions is very similar to anonymous objects. You can access final variables from the local outer scope as well as instance fields and static variables.

a. Accessing Local Variables:

final int num = 1; //should be explicitly or implicitly final
Converter<Integer, String> stringConverter =
(from) -> String.valueOf(from + num); //(parameter) -> return codes, this is a method stringConverter.convert(2); // 3

Writing to num from within the lambda expression is also prohibited.

b. Accessing Fields and Static Variables

In constrast to local variables we have both read and write access to instance fields and static variables from within lambda expressions. This behaviour is well known from anonymous objects.

class 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);
};
}
}

c. Accessing Default Interface Methods

The "default" keyword in Inteface does not work for lambda Interfaces. Default methods cannot be accessed from within lambda expressions.

6. Built-in Functional Interfaces

The JDK 1.8 API contains many built-in functional interfaces. Some of them are well known from older versions of Java like Comparator or Runnable. Those existing interfaces are extended to enable Lambda support via the @FunctionalInterface annotation.

But the Java 8 API is also full of new functional interfaces to make your life easier. Some of those new interfaces are well known from the Google Guava library. Even if you're familiar with this library you should keep a close eye on how those interfaces are extended by some useful method extensions.

Predicates

//http://howtodoinjava.com/2014/04/04/how-to-use-predicate-in-java-8/
Predicate<String> predicate = (s) -> s.length() > 0; predicate.test("foo"); // true
predicate.negate().test("foo"); // false Predicate<Boolean> nonNull = Objects::nonNull;
Predicate<Boolean> isNull = Objects::isNull; Predicate<String> isEmpty = String::isEmpty;
Predicate<String> isNotEmpty = isEmpty.negate();

Functions

Functions accept one argument and produce a result. Default methods can be used to chain multiple functions together (compose, andThen).

Function<String, Integer> toInteger = Integer::valueOf;
Function<String, String> backToString = toInteger.andThen(String::valueOf); backToString.apply("123"); // "123"

Suppliers & Consumers

Suppliers produce a result of a given generic type. Unlike Functions, Suppliers don't accept arguments.

Supplier<Person> personSupplier = Person::new;  //http://www.byteslounge.com/tutorials/java-8-consumer-and-supplier
personSupplier.get(); // new Person

Consumers represents operations to be performed on a single input argument.

Consumer<Person> greeter = (p) -> System.out.println("Hello, " + p.firstName);
greeter.accept(new Person("Luke", "Skywalker"));

Comparators

Comparators are well known from older versions of Java. Java 8 adds various default methods to the interface.

Comparator<Person> comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName);

Person p1 = new Person("John", "Doe");
Person p2 = new Person("Alice", "Wonderland"); comparator.compare(p1, p2); // > 0
comparator.reversed().compare(p1, p2); // < 0

Optionals

Optionals are not functional interfaces, instead it's a nifty utility to prevent NullPointerException. Optional is a simple container for a value which may be null or non-null. Think of a method which may return a non-null result but sometimes return nothing. Instead of returning nullyou return an Optional in Java 8.

Optional<String> optional = Optional.of("bam");

optional.isPresent();           // true
optional.get(); // "bam"
optional.orElse("fallback"); // "bam" optional.ifPresent((s) -> System.out.println(s.charAt(0))); // "b"

7. Streams

java.util.Stream represents a sequence of elements on which one or more operations can be performed. Stream operations are either intermediate or terminal. While terminal operations return a result of a certain type, intermediate operations return the stream itself so you can chain multiple method calls in a row. Streams are created on a source, e.g. ajava.util.Collection like lists or sets (maps are not supported). Stream operations can either be executed sequential or parallel.

List<String> stringCollection = new ArrayList<>();
stringCollection.add("ddd2");
stringCollection.add("aaa2");
stringCollection.add("bbb1");
stringCollection.add("aaa1");
stringCollection.add("bbb3");
stringCollection.add("ccc");
stringCollection.add("bbb2");
stringCollection.add("ddd1");

Filter

Filter accepts a predicate to filter all elements of the stream. This operation is intermediatewhich enables us to call another stream operation (forEach) on the result. ForEach accepts a consumer to be executed for each element in the filtered stream. ForEach is a terminal operation. It's void, so we cannot call another stream operation.

stringCollection
.stream()
.filter((s) -> s.startsWith("a"))
.forEach(System.out::println); // "aaa2", "aaa1"

Sorted

Sorted is an intermediate operation which returns a sorted view of the stream. The elements are sorted in natural order unless you pass a custom Comparator.

stringCollection
.stream()
.sorted()
.filter((s) -> s.startsWith("a"))
.forEach(System.out::println); // "aaa1", "aaa2"

Keep in mind that sorted does only create a sorted view of the stream without manipulating the ordering of the backed collection. The ordering of stringCollection is untouched:

System.out.println(stringCollection);
// ddd2, aaa2, bbb1, aaa1, bbb3, ccc, bbb2, ddd1

Map

The intermediate operation map converts each element into another object via the given function. The following example converts each string into an upper-cased string. But you can also use map to transform each object into another type. The generic type of the resulting stream depends on the generic type of the function you pass to map.

stringCollection
.stream()
.map(String::toUpperCase)
.sorted((a, b) -> b.compareTo(a))
.forEach(System.out::println); // "DDD2", "DDD1", "CCC", "BBB3", "BBB2", "AAA2", "AAA1"

Match

Various matching operations can be used to check whether a certain predicate matches the stream. All of those operations are terminal and return a boolean result.

boolean anyStartsWithA =
stringCollection
.stream()
.anyMatch((s) -> s.startsWith("a")); System.out.println(anyStartsWithA); // true boolean allStartsWithA =
stringCollection
.stream()
.allMatch((s) -> s.startsWith("a")); System.out.println(allStartsWithA); // false boolean noneStartsWithZ =
stringCollection
.stream()
.noneMatch((s) -> s.startsWith("z")); System.out.println(noneStartsWithZ); // true

Count

Count is a terminal operation returning the number of elements in the stream as a long.

long startsWithB =
stringCollection
.stream()
.filter((s) -> s.startsWith("b"))
.count(); System.out.println(startsWithB); // 3

Reduce

This terminal operation performs a reduction on the elements of the stream with the given function. The result is an Optional holding the reduced value.

Optional<String> reduced =
stringCollection
.stream()
.sorted()
.reduce((s1, s2) -> s1 + "#" + s2); reduced.ifPresent(System.out::println);
// "aaa1#aaa2#bbb1#bbb2#bbb3#ccc#ddd1#ddd2"

8. Parallel Streams

As mentioned above streams can be either sequential or parallel. Operations on sequential streams are performed on a single thread while operations on parallel streams are performed concurrent on multiple threads.

The following example demonstrates how easy it is to increase the performance by using parallel streams.

First we create a large list of unique elements:

int max = 1000000;
List<String> values = new ArrayList<>(max);
for (int i = 0; i < max; i++) {
UUID uuid = UUID.randomUUID();
values.add(uuid.toString());
}

For Sequential Sort

long t0 = System.nanoTime();

long count = values.stream().sorted().count();
System.out.println(count); long t1 = System.nanoTime(); long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println(String.format("sequential sort took: %d ms", millis)); // sequential sort took: 899 ms

For Parallel Sort

long t0 = System.nanoTime();

long count = values.parallelStream().sorted().count();
System.out.println(count); long t1 = System.nanoTime(); long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println(String.format("parallel sort took: %d ms", millis)); // parallel sort took: 472 ms

9. Map

As already mentioned maps don't support streams. Instead maps now support various new and useful methods for doing common tasks.

Map<Integer, String> map = new HashMap<>();

for (int i = 0; i < 10; i++) {
map.putIfAbsent(i, "val" + i);
} map.forEach((id, val) -> System.out.println(val));

The above code should be self-explaining: putIfAbsent prevents us from writing additional if null checks; forEach accepts a consumer to perform operations for each value of the map.

This example shows how to compute code on the map by utilizing functions:

map.computeIfPresent(3, (num, val) -> val + num);
map.get(3); // val33 map.computeIfPresent(9, (num, val) -> null);
map.containsKey(9); // false map.computeIfAbsent(23, num -> "val" + num);
map.containsKey(23); // true map.computeIfAbsent(3, num -> "bam");
map.get(3); // val33

Next, we learn how to remove entries for a a given key, only if it's currently mapped to a given value:

map.remove(3, "val3");
map.get(3); // val33 map.remove(3, "val33");
map.get(3); // null

Another helpful method:

map.getOrDefault(42, "not found");  // not found

Merging entries of a map is quite easy:

map.merge(9, "val9", (value, newValue) -> value.concat(newValue));
map.get(9); // val9 map.merge(9, "concat", (value, newValue) -> value.concat(newValue));
map.get(9); // val9concat

Merge either put the key/value into the map if no entry for the key exists, or the merging function will be called to change the existing value.

Java 8 Learn Notes的更多相关文章

  1. Java 8 Learn Notes - Streams

    Main reference [1] http://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples 1. How Stream ...

  2. Forget Java to learn Javascript from 0.--Day 1

    The first day,when I read 'we need practice so we need a Javascript Interpreter.','Every browser has ...

  3. Forget Java to learn Javascript from 0.--Preface

    I'm going to start to learn Javascript in this month. Someone told me you can't learn another langua ...

  4. [Java coding] leetcode notes

    1, 如何不排序而找到最大,次大或者最小值? var int max1, max2, min1; iterate array once: update max1, max2, min1, for ex ...

  5. Linux Academy Learn Notes

    Linux Essentials Certification Globbing ls ?.txt --- ? stands for one character while * means one or ...

  6. Bash Scripting Learn Notes

    References: [1] http://www.tldp.org/LDP/Bash-Beginners-Guide/html/ 1. Executing programs from a scri ...

  7. Dart Learn Notes 04

    流程控制语句 流程控制语句的作用就是控制代码的执行流程. if and else var a = 10; if(a > 10){ print('ok'); }else if( 5 < a ...

  8. Dart Learn Notes 03

    操作符 dart 有一套自己定义的操作符: 这里我就不再写了,直接copy一份官网的. 如果有过编程基础,上边展示的操作符应该都不陌生. 算术运算符 加: + 减: - 乘: * 除: / 取余: % ...

  9. Dart Learn Notes 02

    Functions Dart是一门面向对象的语言,所以即便是方法也是一个对象,它的类型是Function. 这就意味着方法可以指向变量,也可以作为方法中的参数供其他方法使用.甚至可以让 一个类作为一个 ...

随机推荐

  1. Android Studio查找功能(搜索功能)及快捷键

    版权声明:本文为博主原创文章,未经博主允许不得转载. 1.在当前窗口查找文本[Ctrl+F] F3                  向下查找关键字出现位置 Shift+F3        向上一个关 ...

  2. 在app中屏蔽第三方键盘

    iOS8开放了安装第三方键盘的权限,但是在项目开发中,有些情况是需要禁用第三方键盘的.比如说,数字键盘上需要自定义按钮,但是在第三方键盘弹出时,按钮就覆盖在这上面了,在这中情况下,最好的办法是禁用第三 ...

  3. JavaScript基础学习(二)—JavaScript基本概念

    一.语法 1.区分大小写     JavaScript是一种弱类型的脚本语言.它区分大小写,变量名test与Test表示两个完全不同的变量.   2.标识符      所谓标识符就是变量.函数.属性的 ...

  4. Mysql清理二进制日志的技巧

    1:二进制日志 二进制日志记录了所有的DDL(数据定义语言)语句和DML(数据操作语言)语句,但是不记录包括数据查询的语句.语句以"事件"的形式保存,它描述了数据的更改过程,此日志 ...

  5. 移植 DeepinQQ 到 Fedora 中

    本着自由/开源软件的分享精神创作此文,如有任何权力侵害请联系我,我将积极配合. 移植 DeepinQQ 到 Fedora 中 --也不知道是用移植还是迁移更合适 写在前面 首先,在这里要感谢武汉深之度 ...

  6. 浅谈css中单位px和em,rem的区别-转载

    px是你屏幕设备物理上能显示出的最小的一个点,这个点不是固定宽度的,不同设备上点的长宽.比例有可能会不同.假设:你现在用的显示器上1px宽=1毫米,但我用的显示器1px宽=两毫米,那么你定义一个div ...

  7. LINUX ON AZURE 安全建议(全)

    本文为个人原创,可以自由转载,转载请注明出处,多谢! 本文地址:http://www.cnblogs.com/taosha/p/6399554.html 1.网络与安全规划 Azure 虚拟网络 (V ...

  8. 人生第一次hash

    人生的第一次hash交给了模板题. 讲道理,还没有别人快排要快,就比暴力快那么一点... 难道我写的hash就那么菜么? 我想了想,光是处理字符串就O(n*len).. 这是hash的正确写法吗?我都 ...

  9. 【uwp】浅谈China Daily中数据同步到One Drive的实现

    新版China Daily与旧版相比新增了数据同步的功能,那这个功能具体是如何实现的呢,现在让我们来一起看看. 1.注册应用 开发者中心的应用注册就不用多说了(https://developer.mi ...

  10. jsp实现仿QQ空间新建多个相册名称,向相册中添加照片

    工具:Eclipse,Oracle,smartupload.jar:语言:jsp,Java:数据存储:Oracle. 实现功能介绍: 主要是新建相册,可以建多个相册,在相册中添加多张照片,删除照片,删 ...