说明
内容来自《Java 8 In Action》
示例一
java 8 为异步引入了CompletableFuture,它继承了Future。CompletableFuture能更好的处理异步任务直接的关系,如:某个任务取决去上个的任务的结果。
import cn.hutool.http.HttpUtil;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
public class CompletableFutureMain {
public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> HttpUtil.get("https://www.baidu.com/"));
System.out.println("request after");
String res = future.join();
System.out.println(res);
List<String> urls = Arrays.asList("https://www.baidu.com/", "https://www.qidian.com/");
CompletableFuture<String>[] futures = urls.stream()
.map(url -> CompletableFuture.supplyAsync(() -> HttpUtil.get(url)))
.toArray(size -> new CompletableFuture[size]);
CompletableFuture.allOf(futures);
}
}
CompletableFuture提供了一套类似流的API。
示例二
去重操作
import java.util.Arrays;
import java.util.List;
public class DistinctMain {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream()
.filter(n -> n % 2 == 0)
.distinct()
.forEach(System.out::println);
}
}
示例三
查找操作
import java.util.Arrays;
import java.util.List;
public class FindMain {
public static void main(String[] args) {
List<Integer> someNumbers = Arrays.asList(1, 2, 3, 4, 5, 6);
someNumbers.stream()
.map(i -> i * i)
.filter(i -> i % 3 == 0)
.findFirst()
.ifPresent(i -> System.out.println(i));
}
}
示例四
分解任务,将一个大任务,分解为多个小任务同时执行,以提升整体效率。
import java.util.concurrent.RecursiveTask;
public class ForkJoinSumCalculator extends RecursiveTask<Long> {
private final long[] numbers;
private final int start;
private final int end;
private static final long THRESHOLD = 10000;
public ForkJoinSumCalculator(long[] numbers, int start, int end) {
this.numbers = numbers;
this.start = start;
this.end = end;
}
public ForkJoinSumCalculator(long[] numbers) {
this(numbers, 0, numbers.length);
}
@Override
protected Long compute() {
int length = end - start;
if (length <= THRESHOLD) {
return computeSequentially();
}
ForkJoinSumCalculator leftTask = new ForkJoinSumCalculator(numbers, start, start + length / 2);
leftTask.fork();
ForkJoinSumCalculator rightTask = new ForkJoinSumCalculator(numbers, start + length / 2, end);
long rightResult = rightTask.compute();
long leftResult = leftTask.join();
return leftResult + rightResult;
}
private long computeSequentially() {
long sum = 0;
for (int i = start; i < end; i++) {
sum += numbers[i];
}
return sum;
}
}
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;
public class ForkJoinSum {
public static void main(String[] args) {
long[] numbers = LongStream.rangeClosed(1, 10000000).toArray();
ForkJoinTask<Long> task = new ForkJoinSumCalculator(numbers);
long sum = new ForkJoinPool().invoke(task);
System.out.println(sum);
}
}
示例五
函数的组合使用
import java.util.function.Function;
public class FunctionCompose {
public static void main(String[] args) {
Function<Integer, Integer> f = (x) -> x + 1;
Function<Integer, Integer> g = (x) -> x * 2;
// 函数 = g(f(x))
Function<Integer, Integer> compose = f.andThen(g);
Integer sum = compose.apply(2);
System.out.println(sum);
// 函数 = f(g(x))
compose = f.compose(g);
sum = compose.apply(2);
System.out.println(sum);
}
}
示例六
生成流的多种方式
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.stream.Stream;
public class GenerateStream {
public static void main(String[] args) {
ofWay();
fileWay();
methodWay();
generateWay();
}
private static void ofWay() {
Stream<String> stream = Stream.of("java 8", "lambdas", "in", "action");
stream.map(String::toUpperCase)
.forEach(System.out::println);
}
private static void emptyWay() {
Stream stream = Stream.empty();
}
private static void arrayWay() {
Integer[] numbers = {1, 3, 4, 6, 7, 9, 12};
Stream<Integer> stream = Arrays.stream(numbers);
}
private static void fileWay() {
try (Stream<String> lines = Files.lines(Paths.get("E:\\xs.key"), Charset.defaultCharset())) {
lines.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void methodWay() {
Stream.iterate(0, n -> n + 2)
.limit(10)
.forEach(System.out::println);
}
private static void generateWay() {
Stream.generate(Math::random)
.limit(5)
.forEach(System.out::println);
}
}
示例七
传统责任链模式与lambda方式
public abstract class ProcessingObject<T> {
protected ProcessingObject<T> successor;
public void setSuccessor(ProcessingObject<T> successor) {
this.successor = successor;
}
public T handle(T input) {
T r = handleWork(input);
if (successor != null) {
return successor.handle(r);
}
return r;
}
abstract protected T handleWork(T input);
}
public class HeaderTextProcessing extends ProcessingObject<String> {
@Override
protected String handleWork(String input) {
return "From Raoul, Mario and Alan: " + input;
}
}
public class SpellCheckProcessing extends ProcessingObject<String> {
@Override
protected String handleWork(String input) {
return input.replaceAll("labda", "lambda");
}
}
import java.util.function.Function;
import java.util.function.UnaryOperator;
public class ProcessingMain {
public static void main(String[] args) {
final String input = "Aren't labdas really sexy?!!";
commonProcessing(input);
lambdaProcessing(input);
}
private static void commonProcessing(String input) {
ProcessingObject<String> p1 = new HeaderTextProcessing();
ProcessingObject<String> p2 = new SpellCheckProcessing();
p1.setSuccessor(p2);
String result = p1.handle(input);
System.out.println(result);
}
private static void lambdaProcessing(String input) {
UnaryOperator<String> headerProcess = (s) -> "From Raoul, Mario and Alan: " + s;
UnaryOperator<String> spellProcess = (s) -> s.replaceAll("labda", "lambda");
Function<String, String> pipeline = headerProcess.andThen(spellProcess);
System.out.println(pipeline.apply(input));
}
}
示例八
内部类与lambda
import java.io.File;
import java.io.FileFilter;
public class HiddenFiles {
public static void main(String[] args) {
File[] hiddenFiles = new File(".").listFiles(new FileFilter() {
public boolean accept(File file) {
return file.isHidden();
}
});
System.out.println(hiddenFiles.length);
for (File file : hiddenFiles) {
System.out.println(file.getName());
}
// lambda
new File(".").listFiles(file -> file.isHidden());
new File(".").listFiles(File::isHidden);
}
}