关于java8流操作的简单实用说明

目录

Lambda表达式

Lambda表达式说白了就是简洁的表示匿名参数
举个栗子,在Collector的排序中我们可以自定义比较的方法,代码一般写成

## 比如说商品按照价格排序
Comparator<Goods> comp = new Comparator<Goods> () {
    public int compare(Goods v1, Goods v2) {
        return v1.getPrice() > v2.getPrice();
    }
}

如果替换成jdk中的Lambda表达式的话,可以简化成为

(v1, v2) -> v1.getPrice() > v2.getPrice();

简化了比较类的声明以及各种繁琐的Override,代码看起来更加简洁

数据流操作

流是Java 8 API的一个新的接口,可以使用声明式的方法来处理数据集合,通俗点理解的话可以看做是一个迭代器。

和常见的流以及迭代器一样,Java 8的流都是一次性的。你在遍历到一半的时候,如果你想回退访问上一个数据,抱歉这个不可能,你只能重新开一个新的流或者自己想办法。

ps. 个人认为,在流操作中,最重要的是你要知道当前的流数据中是什么形式的内容。理解这点,在写代码和读代码优化上会更加快捷

后续都以商品类Goods作为举例,代码为伪代码,不一定能执行

public class Goods {
    int price;      // 价格,偷懒算他全部是整数吧
    String name;    // 商品名称
    int category;   // 商品类目
}

流中常用的函数说明

stream(打开数据流)

List<Goods> list = goodsDAO.getSomeGoods();
list.stream().doSomething();

通过stream()方法,可以得到一个商品类的流。
另外还有parallelStream()方法,也是一个获取流的方法,但是这个是一个并发流,可以充分使用多线程进行操作,不保障线程安全,具体看你的写法。

collect(数据收集)

List<Goods> newList = list.stream().doSomething().collect(Collectors.toList());

通过stream()方法得到的是一个流,如果想要得到一个数据还得将流中的数据收集起来

filter(过滤)

// 获取列表中价格大于100元的商品
list.stream().filter(v -> v.getPrice() > 100).collect(Collectors.toList());

distinct(去重)

limit(截断)

list.stream().limit(3).collect(toList())

获取列表的前三个元素

skip(跳过)

list.stream().filter(v -> v.getPrice() > 100).skip(3).collect(toList());

价格大于100,去掉头两个元素,剩余的数据列表

map(映射,常用之一)

通常情况下,我们有一个商品的列表,我们可能需要提取其中的商品价格或者商品名称,以完成一些操作,这时候需要做流中数据的映射

// 获取商品列表中名字带有“促销”字样的商品名字
List<String> onSaleNames = goodsList
                            .stream()       // 此时数据流中对象为Goods对象
                            .map(Goods::getName)    // 通过getName映射,此时流中的对象为商品名称
                            .filter(v -> v.contain("促销")) // 过滤,获取带有需要字样的名称
                            .collect(toList())

reduce(规约,常用之一,通常用来做统计)

// 多线程统计商品列表中所有商品的价格之和
int totalPrice = list.stream().map(Goods::getPrice).reduce(0, (l, r) -> l + r);

reduce(0, (l, r) -> l + r)是一个规约方法,0表示声明一个初始值,并且作为lambda表达式(l, r)中l的初始值,等价于

int totalPrice;
int l = 0;
for (Goods item : goods) {
    int r = item.getPrice();
    l = l + r;
}
totalPrice = l;

如果列表数量很多的时候,几千上万甚至更多,可以使用parallelStream来替代stream

sorted(排序)

和集合工具类中的sort是相似的,传入Comparator方法,然后根据比较方法进行排序

// 按照商品价格升序排列
list.stream().sorted((l, r) -> l.getPrice() - r.getPrice()).collect(toList());

其他偶尔可能用到的方法

  • anyMatch(v -> expr(v)),流中是否有符合条件的对象
  • findFirst(),获取流中第一个数据,通常跟在filter后使用
  • findAny(),获取流中任意一个数据,通常跟在filter后使用,与findFirst()的区别在于,在并发流中,获取第一个数据的复杂度更高,findAny()有着更好的效率。

几个无聊的示例

  1. 求带有“折扣”字样商品的价格总和
int price = list.stream()
                .filter(v -> v.getName().contain("折扣"))
                .map(v::getPrice)
                .reduce(0, (l, r) -> l + r);
  1. 比如双十一计算购物车商品列表中的折后价
// 这个是计算折后价的方法,里边一堆子判断逻辑
private void calSingleDogPrice(Goods good) {
    SingleRule rule = getRule();
    // 计算折后价
    good.setPrice(rule.act(good));
}

// 写在同一个类下的时候,可以通过this::Method这种方式来对流中每个对象都调用了一次Method方法,传入Goods对象
list.stream().forEach(this::calSingleDogPrice);

猜你喜欢

转载自blog.csdn.net/luzhyi/article/details/85223344
今日推荐