栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java1.8 流式计算:利用接口的函数式编程 + 链式编程

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java1.8 流式计算:利用接口的函数式编程 + 链式编程

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 extends Collection {
    ...
}

//ArrayList类
public class ArrayList extends AbstractList
        implements List, RandomAccess, Cloneable, java.io.Serializable
{
    ...
}

//Collection接口
public interface Collection extends Iterable {
    ...
    @Override
    default Spliterator spliterator() {
        return Spliterators.spliterator(this, 0);
    }
    
    default Stream 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  Stream stream(Spliterator 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 extends baseStream> {

    Stream filter(Predicate predicate);
    
     Stream map(Function mapper);
    
    Stream limit(long maxSize);
    
    void forEach(Consumer 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 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 list = Arrays.asList("aaaa", "bbbb", "cccc");
        list.forEach(s -> System.out.println(s));  //forEach传入的是consumer接口(入参,无返回)
    }
}

"::"官网对这个符号的解释是方法引用(函数式编程),也就是引用一个方法的意思,英文名称Method References
lambda expressions 可以用来创建一匿名的方法, 这个匿名的方式你需要自己实现。

list.forEach(new Consumer() {
            @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 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 > Comparator comparing(
            Function keyExtractor){
    Objects.requireNonNull(keyExtractor);
        return (Comparator & Serializable)
            (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}

Sensor::getNum表示Sensor类中的getNum方法。

2)Function

函数型接口:有入参,有返回值

//@detail
@FunctionalInterface
public interface Function {

    
    R apply(T t);
}
public void testFunction() {
    // JDK1.8之前的写法
    Function f1 = new Function() {
        @Override
        public String apply(String s) {
            return s;
        }
    };
    // 替换Lambda写法
    Function f2 = (str) -> {return str;};
    // 精简写法
    Function 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 {

    
    boolean test(T t);
}
public void testPredicate() {
    Predicate predicate = s -> s.contains("abc");
    System.out.println(predicate.test("helloabc"));
}
---
true
4)Consumer (无返回)

消费型接口:有入参,没有返回值。

@FunctionalInterface
public interface Consumer {

    
    void accept(T t);
}
public void testConsumer() {
    Consumer consumer = s -> System.out.println(s);
    consumer.accept("hello");
}
---
hello    
5)Supplier(有返回)

供给型接口:没有参数,只有返回值。

@FunctionalInterface
public interface Supplier {

    
    T get();
}

public void testSupplier() {
    Supplier supplier = () -> "hello";
    System.out.println(supplier.get());
}
---
hello
3、例子
    public OptimalSolWithStrategies getBestInOptimalSols(Listos_list, List cl_list) {

        List optimalSol = new ArrayList();
        //从第二个策略开始级联过滤
        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 temp_list = new ArrayList();
                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 temp_list = new ArrayList();
                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 temp_list = new ArrayList();
                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 temp_list = new ArrayList();
                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);
    }
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/643605.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号