java1.8 流式计算:利用接口的函数式编程 + 链式编程
文章目录
- java1.8 流式计算:利用接口的函数式编程 + 链式编程
- 1、流式计算
- 1)ArrayList和Stream关联的底层解析(Collection的default方法)
- 2)Stream流计算
- 2、四大函数式接口(流计算的核心)
- 1)@FunctionalInterface注解 & "::"符号
- 2)Function
- 3)Predicate
- 4)Consumer (无返回)
- 5)Supplier(有返回)
- 3、例子
1、流式计算
参考
- Java - Stream 流式计算_DJun的博客-CSDN博客
- java接口中的default方法
1)ArrayList和Stream关联的底层解析(Collection的default方法)
在java的流式计算中,以list集合为例,由于Arraylist,LinkedList都实现了List接口,而List接口则继承Collection接口,并且Collection接口中有default关键字修饰的Stream()方法(接口中可以对方法进行实现),因此实现类ArrayList继承了Collection的default方法(stream()等),并且可以通过a_list.stream()来获取返回的Stream对象。
//List接口
public interface List<E> extends Collection<E> {
...
}
//ArrayList类
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
...
}
//Collection接口
public interface Collection<E> extends Iterable<E> {
...
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, 0);
}
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
}

这里有点绕口,要细品,且注意两个知识点:
-
由于集合中加入的对象类型不确定,这里都使用了泛型来表示,使得待会获得的Stream对象类型也带泛型。
-
实现类会继承接口中的default方法,比如:https://blog.csdn.net/wf13265/article/details/79363522
public interface A { public default void a(){ System.out.println("这是A"); } } public class Test implements A{ } public class Main { public static void main(String[] args) { Test t = new Test(); t.a(); //执行接口A中默认的方法 } }
这里还是补充一下:
集合对象是通过Collection接口中的
default stream()方法获取Stream对象的。而Stream毕竟是一个接口,需要有个实现类,这里很明确的是,Stream的实现类只有一个:
ReferencePipeline。
该类对象主要是在Collection接口中的
default stream()中,通过StreamSupport静态方法来创建:public final class StreamSupport { public static <T> Stream<T> stream(Spliterator<T> spliterator, boolean parallel) { Objects.requireNonNull(spliterator); return new ReferencePipeline.Head<>(spliterator, StreamOpFlag.fromCharacteristics(spliterator), parallel); } }
2)Stream流计算
集合对象通过Collection默认的stream()获取Stream对象,接着通过Stream的filter等函数,通过传入不同类型的四种函数式接口(@FunctionalInterface注解过的接口),并实现其中唯一的方法,来实现链式编程,完成集合对象的过滤(stream),排序,映射和最终结果(T)的输出等。
public interface Stream<T> extends BaseStream<T, Stream<T>> {
Stream<T> filter(Predicate<? super T> predicate);
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
Stream<T> limit(long maxSize);
void forEach(Consumer<? super T> action);
}
Java 8 引入了流式操作(Stream),通过该操作可以实现对集合(Collection)的并行处理和函数式操作。用周阳大神的话说就是:SQL就是JAVA,JAVA就是SQL。使用java.util.stream包中的Stream接口即可完成SQL中的计算、order by、where等操作。
根据操作返回的结果不同,流式操作分为中间操作和最终操作两种。最终操作返回一特定类型的结果,而中间操作返回流本身,这样就可以将多个操作依次串联起来。根据流的并发性,流又可以分为串行和并行两种。流式操作实现了集合的过滤、排序、映射等功能。
参考Java 8之流式计算_阳阳的博客-CSDN博客_java流式计算
这里再啰嗦一句:Stream是一个接口,而Stream只有一个实现类,即ReferencePipeline
一个案例搞清楚 Stream 的计算方式:
按以下条件筛选:
1、ID 为偶数
2、age>23
3、name转为大写字母
4、按用户名字母倒叙排列
5、只输出一个用户
public void streamCalcDemo() {
User user1 = new User(1, 18, "lisa");
User user2 = new User(2, 19, "pika");
User user3 = new User(3, 20, "sandy");
User user4 = new User(4, 35, "alice");
User user5 = new User(6, 24, "flask");
List<User> list = Arrays.asList(user1, user2, user3, user4, user5);
list.stream()
.filter(u -> {return u.getId() % 2 == 0;}) //filter参数是
.filter(u -> {return u.getAge() > 23; })
.map((u) -> {
u.setName(u.getName().toUpperCase(Locale.ROOT));
return u;
})
// String 类中自带 compareTo() 方法
// 不是很复杂的排序都不需要实现Comparator接口
.sorted((u1,u2)->{return u2.getName().compareTo(u2.getName());})
.limit(1)
.forEach(item->{
System.out.println(item.toString());
});
}
@Data
@ToString
@AllArgsConstructor
class User {
private int id;
private int age;
private String name;
}
2、四大函数式接口(流计算的核心)
参考
- Java - Stream 流式计算_DJun的博客-CSDN博客
- Java 8之流式计算_阳阳的博客-CSDN博客_java流式计算
- Java双冒号(::)运算符详解
1)@FunctionalInterface注解 & "::"符号
java8 lambda 内部接口需要@FunctionalInterface这个注解,这个注解是一个说明性质的注解
- 被
@FunctionalInterface注解的接口只能有一个抽象方法 @FunctionalInterface只能用于注解接口而不能用在class以及枚举上.- 被
@FunctionalInterface注解的符合规则的接口, 可以用lambda表达式.
public class Main {
public static void main(String[] args) throws Exception {
List<String> list = Arrays.asList("aaaa", "bbbb", "cccc");
list.forEach(s -> System.out.println(s)); //forEach传入的是consumer接口(入参,无返回)
}
}
"::"官网对这个符号的解释是方法引用(函数式编程),也就是引用一个方法的意思,英文名称Method References
lambda expressions 可以用来创建一匿名的方法, 这个匿名的方式你需要自己实现。
list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
list.forEach(s -> System.out.println(s));
//上面两种写法是一样的,下面就是lambda表达式.
参考java8获取list对象中某个字段最大值的对象 - Mark_ZSQ - 简书,
@Test
public void test() {
List<Sensor> sensorMongoList = Lists.newArrayList();
Sensor sensor = new Sensor();
sensor.setId("123123");
sensor.setNum("1");
sensorMongoList.add(sensor);
Sensor sensorTwo = new Sensor();
sensorTwo.setId("3423423");
sensorTwo.setNum("2");
sensorMongoList.add(sensorTwo);
Sensor sensor1 = sensorMongoList.stream().max(Comparator.comparing(Sensor::getNum)).get();
String num = sensor1.getNum();
num = String.valueOf(Integer.parseInt(num) + 1);
System.err.println(num);
}
这里的comparing函数的参数是Function接口
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor){
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
Sensor::getNum表示Sensor类中的getNum方法。
2)Function
函数型接口:有入参,有返回值
//@detail
@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);
}
public void testFunction() {
// JDK1.8之前的写法
Function<String, String> f1 = new Function<String, String>() {
@Override
public String apply(String s) {
return s;
}
};
// 替换Lambda写法
Function<String, String> f2 = (str) -> {return str;};
// 精简写法
Function<String, String> f3 = str -> str;
System.out.println(f1.apply("hello"));
System.out.println(f2.apply("hello"));
System.out.println(f3.apply("hello"));
}
---
hello
hello
hello
3)Predicate
断定型接口:有入参,返回布尔值。
//@detail
@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);
}
public void testPredicate() {
Predicate<String> predicate = s -> s.contains("abc");
System.out.println(predicate.test("helloabc"));
}
---
true
4)Consumer (无返回)
消费型接口:有入参,没有返回值。
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
}
public void testConsumer() {
Consumer<String> consumer = s -> System.out.println(s);
consumer.accept("hello");
}
---
hello
5)Supplier(有返回)
供给型接口:没有参数,只有返回值。
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
public void testSupplier() {
Supplier<String> supplier = () -> "hello";
System.out.println(supplier.get());
}
---
hello
3、例子
/**在多个最优解中按照其他策略进行排序,选择得分最高的*/
public OptimalSolWithStrategies getBestInOptimalSols(List<OptimalSolWithStrategies>os_list, List<Integer> cl_list) {
List<Job> optimalSol = new ArrayList<Job>();
//从第二个策略开始级联过滤
for(int i=1; i < cl_list.size();i++) {
if(cl_list.get(i) == 0){
float max_val = os_list.stream().max(Comparator.comparing(OptimalSolWithStrategies::getPriorityPer)).get().getPriorityPer();
List<OptimalSolWithStrategies> temp_list = new ArrayList<OptimalSolWithStrategies>();
os_list.stream().filter(p->{return p.getPriorityPer() >= max_val;}).forEach(p-> {temp_list.add(p);});//小于max_val的最优解存在temp_list中
os_list = temp_list;
}
else if(cl_list.get(i) == 1){
float max_val = os_list.stream().max(Comparator.comparing(OptimalSolWithStrategies::getNumPer)).get().getNumPer();
List<OptimalSolWithStrategies> temp_list = new ArrayList<OptimalSolWithStrategies>();
os_list.stream().filter(p->{return p.getNumPer() >= max_val;}).forEach(p-> {temp_list.add(p);});//小于max_val的最优解存在temp_list中
os_list = temp_list;
}
else if(cl_list.get(i) == 2){
float max_val = os_list.stream().max(Comparator.comparing(OptimalSolWithStrategies::getTimePer)).get().getTimePer();
List<OptimalSolWithStrategies> temp_list = new ArrayList<OptimalSolWithStrategies>();
os_list.stream().filter(p->{return p.getTimePer() >= max_val;}).forEach(p-> {temp_list.add(p);});//小于max_val的最优解存在temp_list中
os_list = temp_list;
}
else if(cl_list.get(i) == 3){
float max_val = os_list.stream().max(Comparator.comparing(OptimalSolWithStrategies::getResolutionPer)).get().getResolutionPer();
List<OptimalSolWithStrategies> temp_list = new ArrayList<OptimalSolWithStrategies>();
os_list.stream().filter(p->{return p.getResolutionPer() >= max_val;}).forEach(p-> {temp_list.add(p);});//小于max_val的最优解存在temp_list中
os_list = temp_list;
}
}
return os_list.get(0);
}

