-
四大函数式接口
- Function函数式接口-有参、有返回值
- Predicate断定型接口-有参、返回布尔值
- Consumer消费者接口-有参、无返回值
- Supplier生产者接口-无参、有返回值
-
Stream流式计算
-
ForkJoin分支合并
-
Future异步回调
一、四大函数式接口
简化编码技术: Lambda表达式、链式编程、函数式接口、Stream流式计算。
只要是函数式接口,就可以使用Lambda表达式简化
函数式接口:只有一个方法的接口,如 Runnable接口、forEach的参数是一个消费者类型的函数式接口
java.util.Function 包下的 有基本的四大函数式接口
- Function
- Consumer
- Predicate
- Supplier
========== Runnable 接口==========
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
========== foreach的 consumer 参数也是函数式接口 ===========
@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
final int expectedModCount = modCount;
@SuppressWarnings("unchecked")
final E[] elementData = (E[]) this.elementData;
final int size = this.size;
for (int i=0; modCount == expectedModCount && i < size; i++) {
action.accept(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
=========== Consumer 消费者接口 =============
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
/**
* Returns a composed {@code Consumer} that performs, in sequence, this
* operation followed by the {@code after} operation. If performing either
* operation throws an exception, it is relayed to the caller of the
* composed operation. If performing this operation throws an exception,
* the {@code after} operation will not be performed.
*
* @param after the operation to perform after this operation
* @return a composed {@code Consumer} that performs in sequence this
* operation followed by the {@code after} operation
* @throws NullPointerException if {@code after} is null
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
复制代码
1.Function函数式接口
说明
- apply方法接受一个参数t,返回一个参数R
- 可以使用Lambda表达式简化
源码
/**
* Represents a function that accepts one argument and produces a result.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #apply(Object)}.
*
* @param <T> the type of the input to the function
* @param <R> the type of the result of the function
*
* @since 1.8
*/
@FunctionalInterface
public interface Function<T, R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t); ======》 接受一个参数 t 返回 R
/**
* Returns a composed function that first applies the {@code before}
* function to its input, and then applies this function to the result.
* If evaluation of either function throws an exception, it is relayed to
* the caller of the composed function.
*
* @param <V> the type of input to the {@code before} function, and to the
* composed function
* @param before the function to apply before this function is applied
* @return a composed function that first applies the {@code before}
* function and then applies this function
* @throws NullPointerException if before is null
*
* @see #andThen(Function)
*/
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
/**
* Returns a composed function that first applies this function to
* its input, and then applies the {@code after} function to the result.
* If evaluation of either function throws an exception, it is relayed to
* the caller of the composed function.
*
* @param <V> the type of output of the {@code after} function, and of the
* composed function
* @param after the function to apply after this function is applied
* @return a composed function that first applies this function and then
* applies the {@code after} function
* @throws NullPointerException if after is null
*
* @see #compose(Function)
*/
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
/**
* Returns a function that always returns its input argument.
*
* @param <T> the type of the input and output objects to the function
* @return a function that always returns its input argument
*/
static <T> Function<T, T> identity() {
return t -> t;
}
}
复制代码
举例
package study_function;
import java.util.function.Function;
/**
* Function函数式接口
*/
public class Demo1 {
public static void main(String[] args) {
// 一般形式
Function function = new Function<String,String>() {
@Override
public String apply(String str) {
return str;
}
};
// 使用Lambda 简化
Function function1 = (str)->{ return str;};
Function function2 = str-> {return str;};
System.out.println(function.apply("xiaosi")); // 输出 xiaosi
System.out.println(function1.apply("xiaosi")); // 输出 xiaosi
System.out.println(function2.apply("xiaosi")); // 输出 xiaosi
}
}
复制代码
2.Predicate断定型接口
说明
- 断定型接口
- 接受一个参数,返回值是布尔型
源码
/**
* Represents a predicate (boolean-valued function) of one argument.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #test(Object)}.
*
* @param <T> the type of the input to the predicate
*
* @since 1.8
*/
@FunctionalInterface
public interface Predicate<T> {
/**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
boolean test(T t);
/**
* Returns a composed predicate that represents a short-circuiting logical
* AND of this predicate and another. When evaluating the composed
* predicate, if this predicate is {@code false}, then the {@code other}
* predicate is not evaluated.
*
* <p>Any exceptions thrown during evaluation of either predicate are relayed
* to the caller; if evaluation of this predicate throws an exception, the
* {@code other} predicate will not be evaluated.
*
* @param other a predicate that will be logically-ANDed with this
* predicate
* @return a composed predicate that represents the short-circuiting logical
* AND of this predicate and the {@code other} predicate
* @throws NullPointerException if other is null
*/
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
/**
* Returns a predicate that represents the logical negation of this
* predicate.
*
* @return a predicate that represents the logical negation of this
* predicate
*/
default Predicate<T> negate() {
return (t) -> !test(t);
}
/**
* Returns a composed predicate that represents a short-circuiting logical
* OR of this predicate and another. When evaluating the composed
* predicate, if this predicate is {@code true}, then the {@code other}
* predicate is not evaluated.
*
* <p>Any exceptions thrown during evaluation of either predicate are relayed
* to the caller; if evaluation of this predicate throws an exception, the
* {@code other} predicate will not be evaluated.
*
* @param other a predicate that will be logically-ORed with this
* predicate
* @return a composed predicate that represents the short-circuiting logical
* OR of this predicate and the {@code other} predicate
* @throws NullPointerException if other is null
*/
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
/**
* Returns a predicate that tests if two arguments are equal according
* to {@link Objects#equals(Object, Object)}.
*
* @param <T> the type of arguments to the predicate
* @param targetRef the object reference with which to compare for equality,
* which may be {@code null}
* @return a predicate that tests if two arguments are equal according
* to {@link Objects#equals(Object, Object)}
*/
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
复制代码
举例
package study_function;
import java.util.function.Predicate;
/**
* Predicate 判定性接口
*/
public class Demo2_predicate {
public static void main(String[] args) {
// 一般方式
Predicate<String> predicate = new Predicate<String>() {
@Override
public boolean test(String s) {
if(!s.isEmpty() && s.length() >= 3){
return true;
}
return false;
}
};
// 使用lambda简化
Predicate<String> predicate1 = (s)->{
if((!s.isEmpty()) && (s.length() >= 3)) {
return true;
}
return false;
};
System.out.println(predicate.test("xiaosi")); // true
System.out.println(predicate1.test("xiaosi")); // true
}
}
复制代码
3.Consumer消费者接口
说明
- 接受一个参数,无返回值
源码
/**
* Represents an operation that accepts a single input argument and returns no
* result. Unlike most other functional interfaces, {@code Consumer} is expected
* to operate via side-effects.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #accept(Object)}.
*
* @param <T> the type of the input to the operation
*
* @since 1.8
*/
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
/**
* Returns a composed {@code Consumer} that performs, in sequence, this
* operation followed by the {@code after} operation. If performing either
* operation throws an exception, it is relayed to the caller of the
* composed operation. If performing this operation throws an exception,
* the {@code after} operation will not be performed.
*
* @param after the operation to perform after this operation
* @return a composed {@code Consumer} that performs in sequence this
* operation followed by the {@code after} operation
* @throws NullPointerException if {@code after} is null
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
复制代码
举例
package study_function;
import java.util.function.Consumer;
/**
* Consumer 消费者接口
*/
public class Demo3_consumer {
public static void main(String[] args) {
// 一般方式生产一个字符串
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println("消费了====》 " + s);
}
};
// 使用Lambda表达式简化
Consumer<String> consumer1 = (str)->{
System.out.println("消费了===》" + str);
};
consumer.accept("xiaosi"); // 消费了====》 xiaosi
consumer1.accept("si");// 消费了====》 si
}
}
复制代码
4.Supplier生产者接口
说明
- 无输入参数,有返回值
源码
package java.util.function;
/**
* Represents a supplier of results.
*
* <p>There is no requirement that a new or distinct result be returned each
* time the supplier is invoked.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #get()}.
*
* @param <T> the type of results supplied by this supplier
*
* @since 1.8
*/
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
复制代码
二、Stream流式计算
什么是Stream流式计算
- 常用的集合是为了存储数集,而对于集合数据的一些处理(像筛选集合数据等)可以使用Stream流来处理
- java.util.tream包下的Stream接口 支持顺序和并行聚合操作的一系列元素
- Stream流可以结合四大函数式接口进行数据处理(方法的参数支持函数式接口)
使用
集合.stream()
可以将集合对象 转为 流对象,调用流对象的一些方法进行数据操作- 常用方法
filter(Predicate<? super T> predicate) 返回由与此给定谓词匹配的此流的元素组成的流。
- count() 返回此流中的元素数。
- forEach(Consumer<? super T> action) 对此流的每个元素执行操作。
- sorted(Comparator<? super T> comparator) 返回由该流的元素组成的流,根据提供的 Comparator进行排序。
- map(Function<? super T,? extends R> mapper)返回由给定函数应用于此流的元素的结果组成的流。
- sorted(Comparator<? super T> comparator)返回由该流的元素组成的流,根据提供的 Comparator进行排序。
举例
package study_stream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class Demo1 {
public static void main(String[] args) {
User user1 = new User("xiaosi1",20,18000);
User user2 = new User("xiaosi2",21,19000);
User user3 = new User("xiaosi3",23,20000);
User user4 = new User("xiaosi4",24,21000);
User user5 = new User("xiaosi5",25,22000);
User user6 = new User("xiaosi6",26,23000);
List<User> list = Arrays.asList(user1,user2,user3,user4,user5,user6);
// 1. forEach
list.stream().forEach((user)->{
System.out.println(user);
});
list.stream().close();
System.out.println("===================");
//2. filter、Predicate判定式函数接口
// 筛选年龄在21之上,薪水在20000以上的user
list.stream().
filter((user)->{ return user.getSalary() > 20000; }).
filter((user)->{return user.getAge()>= 21; }).
forEach(System.out::println);
list.stream().close();
System.out.println("==================");
// 3. map(Function<? super T,? extends R> mapper)
//返回由给定函数应用于此流的元素的结果组成的流。
// salary排序
list.stream().
filter((user)->{return user.getSalary() < 20000; }).
map((user)->{ return user.getSalary() + 2000; }). // 返回salary,18000 + 2000 、19000 + 2000
sorted((u1,u2)->{ return u1.compareTo(u1); }).
forEach(System.out::println);
list.stream().close();
}
}
class User{
private String name;
private int age;
private int salary;
public User(String name, int age, int salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}';
}
}
输出:
User{name='xiaosi1', age=20, salary=18000}
User{name='xiaosi2', age=21, salary=19000}
User{name='xiaosi3', age=23, salary=20000}
User{name='xiaosi4', age=24, salary=21000}
User{name='xiaosi5', age=25, salary=22000}
User{name='xiaosi6', age=26, salary=23000}
===================
User{name='xiaosi4', age=24, salary=21000}
User{name='xiaosi5', age=25, salary=22000}
User{name='xiaosi6', age=26, salary=23000}
==================
20000
21000
复制代码
三、ForkJoin分支合并
概念
-
通过FokeJoinPool实例调用方法
- void execute(ForkJoinTask<?> task) 为异步执行给定任务的排列。
- void execute(Runnable task) 在将来的某个时间执行给定的命令。
- T submit(ForkJoinTask task) 提交一个ForkJoinTask来执行。返回当前任务,在调用get()方法拿到返回值
-
执行任务的方法参数为ForkJoinTask,实现子类有
- RecursiveAction 递归事件,无返回值
- RecursiveTask 递归任务,有返回值
-
MyTask继承ForkJoinTask<返回值>,重写 compute计算方法
-
最后执行
- ForkJoinPool forkJoinPool = new ForkJoinPool();
- ForkJoinTask res = forkJoinPool.submit(myTask);
- System.out.println(res.get());
举例
============ MyRecursiveTask ========
package study_fokejoin;
import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
/**
* 计算 1 - 10_0000_0000的累和
* 使用分支合并
*/
public class MyRecursiveTask extends RecursiveTask<Long> {
private Long start = 1L;
private Long end;
// 临界值,判断选择分支合并 还是 一般方法
private Long temp = 10000L;
long sum = 0L;
public MyRecursiveTask(Long start, Long end) {
this.start = start;
this.end = end;
}
// 分支合并计算方法
@Override
protected Long compute() {
// 一般方法
if((end - start) < temp){
for (long i = start; i <= end; i++) {
sum += i;
}
return sum;
} // ForkJoin方法
else{
long mid = (start + end) /2;
// 拆分任务,将任务压入线程队列
MyRecursiveTask task1 = new MyRecursiveTask(start,mid);
task1.fork();
MyRecursiveTask task2 = new MyRecursiveTask(mid+1,end);
task2.fork();
// 合并子任务结果
long sum = task1.join() + task2.join();
return sum;
}
}
}
============ Test ===============
package study_fokejoin;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 使用FokrJoin计算
MyRecursiveTask task = new MyRecursiveTask(1L,10_0000_0000L);
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinTask<Long> res = forkJoinPool.submit(task);
System.out.println(res.get());
// 使用并行Stream流
System.out.println(LongStream.rangeClosed(1L, 10_0000_0000L).parallel().reduce(0, Long::sum));
}
}
复制代码
四、异步回调
概念
- 类似ajax技术,可以进行异步执行、成功回调、失败回调。
- java.util.concurrent包下的 接口Future,有
- 实现子类:CompletableFuture , CountedCompleter , ForkJoinTask , FutureTask , RecursiveAction , RecursiveTask , SwingWorker
- CompletableFuture 有静态方法
- 无返回结果
- 有返回结果
举例
package study_future;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
public class Demo1 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
test2();
}
// 1. 无返回值的 异步
static void test1() throws ExecutionException, InterruptedException {
CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(()->{
try {
TimeUnit.SECONDS.sleep(3);
System.out.println("异步任务执行了!!");
} catch (Exception e) {
e.printStackTrace();
} finally {
}
});
System.out.println("xiaosi1");
completableFuture.get();
}
// 2. 有返回值的 异步
static void test2() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(()->{
int num = 10 / 0;
try {
TimeUnit.SECONDS.sleep(3);
return 1;
} catch (Exception e) {
e.printStackTrace();
return -1;
}
});
System.out.println("xiaosi2");
completableFuture.whenCompleteAsync((t,u)->{
System.out.println(t+"=====> " + t); // 成功的时候返回值
System.out.println(u+"=====> " + u); // 失败的信息
System.out.println("有返回值的异步执行了!");
}).exceptionally((e)->{ // 异常捕获
e.printStackTrace();
return 404;
}).get();
}
}
复制代码