1. 程式人生 > >關於java8流操作的簡單實用說明

關於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);