java8-Stream 流 常用API使用

類準備:

List<Dish> menu = Arrays.asList(
        new Dish("pork", false, 800, Type.MEAT),
        new Dish("beef", false, 700, Type.MEAT),
        new Dish("chicken", false, 400, Type.MEAT),
        new Dish("french fries", true, 530, Type.OTHER),
        new Dish("rice", true, 350, Type.OTHER),
        new Dish("season fruit", true, 120, Type.OTHER),
        new Dish("pizza", true, 550, Type.OTHER),
        new Dish("prawns", false, 300, Type.FISH),
        new Dish("prawns", false, 300, Type.FISH),
        new Dish("prawns", false, 300, Type.FISH),
        new Dish("salmon", false, 450, Type.FISH) );

List<Integer> numbers = Arrays.asList(1,1,4,10,343,22,345,21);

public class Dish {
    private final String name;
    private final boolean vegetarian;
    private final int calories;
    private final Type type;
    public Dish(String name, boolean vegetarian, int calories, Type type) {
        this.name = name;
        this.vegetarian = vegetarian;
        this.calories = calories;
        this.type = type;
    }
    public String getName() {
        return name;
    }
    public boolean isVegetarian() {
        return vegetarian;
    }
    public int getCalories() {
        return calories;
    }
    public Type getType() {
        return type;
    }
    @Override
    public String toString() {
        return name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Dish dish = (Dish) o;
        return vegetarian == dish.vegetarian &&
                calories == dish.calories &&
                Objects.equals(name, dish.name) &&
                type == dish.type;
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, vegetarian, calories, type);
    }


public enum Type {

    MEAT,FISH,OTHER
}

篩選和切片

filter方法:

該操作會接受一個返回boolean的函數作爲參數,並返回一個包括所有符合條件的元素的流

List<Dish> vegetarianMenu = menu.stream().filter(Dish::isVegetarian).collect(Collectors.toList());
distinct方法:

它會返回一個元素各異【不含相同值】(根據流所生成元素的hashCode和equals方法實現)的流 —》 【去重】
對於對象一定要重寫hashCode和equals方法

List<Dish> vegetarianMenuDis = menu.stream().distinct().collect(Collectors.toList());
limit方法:

該方法會返回一個不超過給定長度的流
limit作用在有序集合上同時也可作用在無序集合上,都是返回前n個元素

List<Dish> vegetarianMenuLimit = menu.stream().limit(3).collect(Collectors.toList());
skip方法:

返回一個扔掉了前n個元素的流,如果流中元素不足n個,則返回一個空流。

List<Dish> vegetarianMenuSkip = menu.stream().skip(3).collect(Collectors.toList());

映射

map方法:

接受一個函數作爲參數這個函數會被應用到每個元素上,並將其映射成一個新的元素

List<String> dishName = menu.stream().map(Dish::getName).collect(Collectors.toList());
List<Integer> dishlength= menu.stream().map(Dish::getName).map(String::length).collect(Collectors.toList());
Arrays.stream():

接受一個數組併產生一個流

String[] arrayOfWords = {"Goodbye", "World"};
Stream<String> streamOfwords = Arrays.stream(arrayOfWords);
flatMap方法:

將各個數組映射成流的內容,並不是分別映射成一個流
flatmap方法把一個流中的每個值都換成另一個流,然後把所有的流連接起來成爲一個流。

將list中的單詞切割,去除重複字母
List<String> words = Arrays.asList("hello","world");
List<String> wordsF = words.stream().map((String w) -> w.split("")).flatMap(Arrays::stream).distinct().collect(Collectors.toList());

組合成一個二維數組
List<Integer> numbers1 = Arrays.asList(1, 2, 3);
List<Integer> numbers2 = Arrays.asList(3, 4);
List<int[]> pairs = numbers1.stream()
        .flatMap((Integer i) -> numbers2.stream().map((Integer j) -> new int[]{i, j}))
        .collect(Collectors.toList());

查找和匹配

anyMatch方法:

檢查輸入的條件是否至少匹配一個元素,是一個終端操作
anyMatch方法返回一個boolean

boolean isAny = menu.stream().anyMatch(Dish::isVegetarian);
allMatch方法:

檢查輸入的條件是否匹配所有元素

boolean isAll = menu.stream().allMatch(d -> d.getCalories() > 300);
noneMatch方法:

allMatch的反義詞,沒有任何元素與給定的條件匹配

boolean isNone = menu.stream().noneMatch(d -> d.getType().equals("XXX"));
findAny方法:

返回當前流中的任意元素

Optional<Dish> dish = menu.stream().findAny();

Optional<T>類(java.util.Optional)是一個容器類,代表一個值存在或不存在。
findFirst方法

查找第一個元素

Optional<Dish> firstDish = menu.stream().findFirst();

何時使用findFirst和findAny:
找到第一個元素在並行上有更多的限制,如果不關心返回的元素是哪個,則使用findAny,它在使用並行流時限制較少

歸約

reduce方法
將流中所有元素反覆結合起來,得到一個值
educe接受兩個參數:
一個初始值,這裏是0;
一個BinaryOperator<T>來將兩個元素結合起來產生一個新值

求和運算
1.使用map轉換成int
2.使用reduce將所有元素相加
int sum = menu.stream().map(Dish::getCalories).reduce(0,(a,b) -> a+b);
int sum = menu.stream().map(Dish::getCalories).reduce(0,(a,b) -> a*b);
int sum = menu.stream().map(Dish::getCalories).reduce(0,(a,b) -> a-b);
int sum = menu.stream().map(Dish::getCalories).reduce(0,(a,b) -> a/b);


int sum = numbers.stream().reduce(0, Integer::sum);


最大值
List<Integer> numbers = Arrays.asList(1,1,4,10,343,22,345,21);
Optional<Integer> max = numbers.stream().reduce(Integer::max);


最小值
Optional<Integer> min = numbers.stream().reduce(Integer::min);
count方法:

返回集合中對象的總個數

long count = numbers.stream().count();

原始類型流特化,專門支持處理數值流

IntStream、 DoubleStream和LongStream,分別將流中的元素特化爲int、 long和double
解決問題:避免了暗含的裝箱成本

映射到數值流

將流轉換爲特化版本的常用方法是mapToInt、 mapToDouble和mapToLong

int sumMp = menu.stream().mapToInt(Dish::getCalories).sum();
mapToInt返回一個IntStream流。
如果流是空的, sum默認返回0

IntStream還支持其他的方便方法,如max、 min、 average等。

轉換回對象流
IntStream intStream = menu.stream().mapToInt(Dish::getCalories);
Stream<Integer> stream1 = intStream.boxed();
默認值OptionalInt

對於三種原始流特化,也分別有一個Optional原始類型特化版本: OptionalInt、 OptionalDouble和OptionalLong
爲了區分到底是最大值0還是沒有值返回的0

OptionalInt maxCalories = menu.stream().mapToInt(Dish::getCalories).max();

如果沒有最大值的話,顯式提供一個默認最大值

int max = maxCalories.orElse(1);
數值範圍

IntStream和LongStream ---->>> range【起始值,不包含結束值】和rangeClosed【結束值,包含結束值】

1-100以內的偶數
IntStream evenNumbers = IntStream.rangeClosed(1, 100).filter(n -> n % 2 == 0);
遍歷1:
evenNumbers.forEach(i -> System.out.println(i));
遍歷2int[] arraysp = evenNumbers.toArray();
for (int i = 0; i < arraysp.length; i++) {
    System.out.println(arraysp[i]);
}
由值創建流

靜態方法Stream.of,通過顯式值創建一個流。可以接受任意數量的參數
字符流,轉換成大寫輸出

Stream<String> stringStream = Stream.of("a","b","c");
stringStream.map(String::toUpperCase).forEach(System.out::println);
空流
Stream<String> emptyStream = Stream.empty();
由數組創建流

靜態方法Arrays.stream,創建一個數組流,接受一個數組作爲參數

int[] ints = {2, 3, 5, 7, 11, 13};
int suml = Arrays.stream(ints).sum();
由文件生成流
data.txt
google-mysql-mysql-Python-google-mysql-java
java-mysql 
Python-Python-mysql
mysql-google-google-java
查看一個文件中有多少不相同的單詞
long uniqueWords = 0;`在這裏插入代碼片`
try (Stream<String> lines = Files.lines(Paths.get("d://data.txt"),Charset.defaultCharset())){
    uniqueWords = lines.flatMap(line -> Arrays.stream(line.split("-"))).distinct().count();
}catch (IOException e){
    e.printStackTrace();
}

Files.lines:返回一個由指定文件中的各行構成的字符串流
由函數生成流:創建無限流

Stream API提供了兩個靜態方法來從函數生成流: Stream.iterate和Stream.generate。
這兩個操作可以創建無限流:和固定集合創建的流不一樣,沒有固定的大小,按需創建值;爲了避免無窮打印無窮個的值,需要加以limit(n)進行限制

迭代:Stream.iterate

有序,結果取決於前一次應用
此操作生成一個無限流——這個流沒有結尾,因爲值是按需計算的,可以永遠計算下去。
使用limit限制無限循環
獲取10個偶數

Stream.iterate(0,n -> n+2).limit(10).forEach(System.out::println);

斐波納契元組序列
Stream.iterate(new int[]{0,1},t -> new int[]{t[1],t[0]+t[1]})
        .limit(10)
        .forEach(t -> System.out.println("["+t[0]+","+t[1]+"]"));
        
斐波納契數列
Stream.iterate(new int[]{0,1},t -> new int[]{t[1],t[0]+t[1]})
        .limit(10)
        .map(t -> t[0])
        .forEach(System.out::println);
生成:Stream.generate

generate不是依次對每個新生成的值應用函數的。它接受一個Supplier類型的Lambda提供新的值
生成5個double類型的隨機數

Stream.generate(Math::random).limit(5).forEach(System.out::println);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章