java8 函数式编程

1、简单的lamda表达式

如果一个接口中有多个方法,lamda不支持

interface A {
    void testA();
}

interface B {
    void testB(int x);
}

public class Test{

    public static void main(String[] args) {
        //不带参数的lamda表达式
        A a = ()->{ /*TODO*/  };
        //只有一条语句的lamda表达式
        B b = x -> System.out.println(x);
        //带参数的lamda表达式
        B b1 = (int x) -> { /*TODO*/ };
    }
}
2、流
public class Test{
    static ArrayList<Integer> list = new ArrayList<>();
    public static void main(String[] args) {
        for (int i = 0; i < 30; i++) {
            list.add(i);
        }
        //迭代器遍历
        Iterator<Integer> iterator = list.iterator();
        while(iterator.hasNext()) {
            Integer data = iterator.next();
            if(data == 10) {
                System.out.println("find data==>"+10);
            }
        }
        //使用流进行遍历
        long count = list.stream().filter(data -> {
            if(data==10) {
                System.out.println("find data==>" + 10);
                return true;
            }
            return false;
        }).count();
        System.out.println("count==>"+count);
    }
}

以上都是遍历集合,查找并打印。
第一种使用迭代器操作
第二种使用流操作

filter为过滤方法,只是描述stream,但是不会做什么实质的工作。这种方法叫做懒性求值方法。
count会从stream产生值,叫做及早求值方法

2.1 一些常用的流操作

2.1.1
List<String> list = Stream.of("a", "b", "c").collect(Collectors.toList());
of方法将一组初始值生成新的Stream。
collect方法将Stream中的值生成一个集合。

2.1.2

public static void main(String[] args) {
        List<Integer> src = new ArrayList<>();
        for (int i = 0; i < 10; i++)
            src.add(i);

        List<String> dst = src.stream()
                .map(x -> String.valueOf(x))
                .collect(Collectors.toList());
    }

map中的参数其实是一个Function接口
map方法将参数从一种类型转换为另一种类型,这两种类型可以毫无关系。

2.1.3

List<Integer> dst = src.stream()
                .filter(x -> x<10)
                .collect(Collectors.toList());

filter的参数是Predicate接口,参数返回boolean。Stream值保留返回true的值。

2.1.4

import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;

        List<Integer> list = Stream.of(asList(1, 2), asList(3, 4))
                .flatMap(numbers -> numbers.stream())
                .collect(toList());

flatmap将多个stream合并为一个stream

2.1.5

int min = Stream.of(1, 2, 3, 4, 5)
                .min(Comparator.comparing(x -> x))
                .get();

min/max 获取最小/最大值,需要实现Comparator接口

2.1.6

int count = Stream.of(1, 2, 3, 4, 5)
        .reduce(0, (acc, element) -> acc+element);

reduce可以将一组值生成一个值,count,min, max都是reduce的一种。

需要注意的是在lamda函数其实是接口,会设计内部方法自动添加final字段

3.1 基本类型
IntSummaryStatistics res = list.stream().mapToInt(x -> x).summaryStatistics();
res.getSum();
res.getMax();

lamda封装了基本类型的操作,可以使用mapToxxx方法进行具体的转换。
调用summaryStatistics方法将返回xxxSummaryStatistics.里面封装了具体的求最大值、最小值、和、平均值等操作。

3.2 @FunctionalInterface

FunctionalInterface注解用于标识lamda接口,将代码块作为数据打包起来。
该注解会强制javac检查一个接口是否符合lamda函数接口的标准。如果该注解添加在枚举、类、另一个注解或者接口不止一个抽象方法,javac会报错。重构代码时,可以很容易发现问题。

3.3 方法引用
//data为Model类型
l//amda表达式片段为
data -> data.get();
//等价于
Model::get
3.4 collect收集器

3.4.1
LinkedBlockingQueue res = list.stream().collect(Collectors.toCollection(LinkedBlockingQueue::new));

Collectors.toCollection方法可以将集合转换为任意Set或Collectoion的子类

3.4.2
求值操作,如求最大值、最小值、平均值。需要注意返回类型。求值操作可以有具体的类型,如averagingInt、averagingXXX

class Model {
    private int data;
    public int getData() {
        return data;
    }
    public Model(int data){
        this.data = data;
    }
}
public class Test{
    public static void main(String[] args) {
        List<Model> list = new ArrayList<>();
        for (int i = 0; i < 10; i++)
            list.add(new Model(i));
        //平均值
        double res = list.stream().collect(Collectors.averagingInt(Model::getData));
        //求最大值
        Optional<Model> d = list.stream().collect(maxBy(comparing(Model::getData)));
    }
}

3.4.3

Map<Boolean, List<Model>> res = list.stream().collect(partitioningBy(x -> x.getData() > 5));

partitioningBy可以将一个集合按照条件分割成多个集合

3.4.4
组合收集器,可以将多个操作组合使用。

Map<Integer, Long> res = list.stream().collect(groupingBy(x -> x.getData(), counting()));

groupingBy可以将两个操作一起返回。
x -> x.getData()对应Map的Integer,counting()对应Map的Long

4、并行流处理

普通流调用parallel()或集合调用parallelStream()即可获得一个拥有并行能力的流。

并行处理的性能
数据的大小:并行处理是将数据分割、处理、合并。数据量足够大才能充分体现效率。
源数据结构:
ArrayList、数组或者IntStream支持随机读取的数据结构容易分割。性能较好
HashSet、TreeSet这些不容易分割,但是可以分割。性能一般
LinkedList、Streams.iterate等需要O(N)时间复杂度来分解问题,性能较差
装箱:基本类型比装箱类型效果好
cpu核心数:核心越多,效果越好
单元处理开销:花在流中每个元素的时间越长,效果越好

4.1 并行化数组操作
Arrays.parallelPrefix   //计算数组的和
Arrays.parallelSetAll   //更新数组元素
Arrays.parallelSort     //并行化对数组元素排序
5、调试

使用peek方法可以用于调试打印,不会影响正常的操作
list.stream().peek(natie -> System.out.println("==>"+natie.getData())).count();

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值