int[] numbers = {2,1,3};
Arrays.parallelSort(numbers);
JDK8中引入了函数式编程Lambda表达式,这是Java第一次引入函数式编程的相关内容。对于Java中的函数式接口java.lang.Runnable、java.util.Comparator等,都可以使用Lambda表达式来简化代码。
以Runnable接口为例,创建一个传统线程代码:
public void runThread() {
new Thread(new Runnable() {
public void run() {
System.out.println("Run!");
}
}).start();
}
public void runThreadUseLambda() {
new Thread(() -> {
System.out.println("Run!");
}).start();
}
Lambda表达式的声明方式比较简单,由形式参数和方法体两部分组成,中间通过“->”分隔。形式参数可以不需要包含类型的声明,可以进行
自动推断。方法体可以是简单的表达式或代码块。
比如把一个整数列表按照降序排列可以用下面的代码来简洁实现:
Collections.sort(list, (x, y) -> y - x);
JDK8引入了全新的Stream API。这里的Stream和I/O流不同,它更像具有Iterable的集合类,但行为和集合类有有所不同。使用JDK8中java.util.stream下的API无需编写一行多线程代码,就可以很方便地写出高性能的并发程序。
Stream就如同一个迭代器(Iterator),单向,不可往复,数据只能遍历一次,遍历过一次后即用尽了,像水流过,不可往复。与迭代器不同的是,Stream可以并行化操作,迭代器只能命令式地、串行化操作。当使用串行化方式遍历时,每个item读完后再读下一个。而使用并行化方式遍历时,数据会被分成多个段,其中每个都在不同的线程中处理,然后将结果一起输出。
流的常用构造方式
// 1. Individual values
Stream stream = Stream.of("a", "b", "c");
// 2. Arrays
String [] strArray = new String[] {"a", "b", "c"};
stream = Stream.of(strArray);
stream = Arrays.stream(strArray);
// 3. Collections
List list = Arrays.asList(strArray);
stream = list.stream();
流转换为其他数据结构
// 1. Array
String[] strArray1 = stream.toArray(String[]::new);
// 2. Collection
List list1 = stream.collect(Collectors.toList());
List list2 = stream.collect(Collectors.toCollection(ArrayList::new));
Set set1 = stream.collect(Collectors.toSet());
Stack stack1 = stream.collect(Collectors.toCollection(Stack::new));
// 3. String
String str = stream.collect(Collectors.joining()).toString();
常用数据结构转为流后,就可以进行操作。流的操作通常分为以下三类:
从上述三个类别中分别选取一种操作来进行分析。
map
通过map操作把List
List output = wordList.stream().
map(String::toUpperCase).
collect(Collectors.toList());
forEach
forEach 方法接收一个 Lambda 表达式,然后在 Stream 的每一个元素上执行该表达式。
// Java 8
roster.stream()
.filter(p -> p.getGender() == Person.Sex.MALE)
.forEach(p -> System.out.println(p.getName()));
// Pre-Java 8
for (Person p : roster) {
if (p.getGender() == Person.Sex.MALE) {
System.out.println(p.getName());
}
}
limit/skip
limit 返回 Stream 的前面 n 个元素;skip 则是扔掉前 n 个元素(它是由一个叫 subStream 的方法改名而来)。
public void testLimitAndSkip() {
List persons = new ArrayList();
for (int i = 1; i <= 10000; i++) {
Person person = new Person(i, "name" + i);
persons.add(person);
}
List personList2 = persons.stream().
map(Person::getName).limit(10).skip(3).collect(Collectors.toList());
System.out.println(personList2);
}
private class Person {
public int no;
private String name;
public Person (int no, String name) {
this.no = no;
this.name = name;
}
public String getName() {
System.out.println(name);
return name;
}
}
name1
name2
name3
name4
name5
name6
name7
name8
name9
name10
[name4, name5, name6, name7, name8, name9, name10]
public class LotsOfStrings {
private static final LinkedList LOTS_OF_STRINGS = new LinkedList<>();
public static void main(String[] args) throws Exception {
int iteration = 0;
while (true) {
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 1000; j++) {
LOTS_OF_STRINGS.add(new String("String " + j));
}
}
iteration++;
System.out.println("Survived Iteration: " + iteration);
Thread.sleep(100);
}
}
}
代码会在30次循环之后因OutOfMemoryError异常而结束运行
为什么移除持久代
元空间的优点
JDK8是一次较大的升级,从语言层面升级了并行框架、引入了Lambda表达式、Stream API、升级注解,在虚拟机层面,升级了字符串存储的处理方式,JVM内存的管理结构。现在JDK8版本在社区已经趋于稳定,喜欢这些新特性的,可以考虑把java项目升级到JDK8。