JAVA基础---函数式接口、Stream流
函數式編程
Stream流
一、函數式編程:
1、1.概念
函數式接?在Java中是指:有且僅有?個抽象?法的接?。
函數式接?,即適?于函數式編程場景的接?。?Java中的函數式編程體現就是Lambda,所以函數式接? 就是可以適?于Lambda使?的接?。只有確保接?中有且僅有?個抽象?法,Java中的Lambda才能順利 地進?推導。
1、2.格式
只要確保接?中有且僅有?個抽象?法即可:
修飾符 interface 接?名稱 {public abstract 返回值類型 ?法名稱(可選參數信息);// 其他?抽象?法內容 }由于接?當中抽象?法的 public abstract 是可以省略的,所以定義?個函數式接?很簡:
public interface MyFunctionalInterface {void myMethod(); }1、3.自定義函數式接口
對于剛剛定義好的 MyFunctionalInterface 函數式接?,典型使?場景就是作為?法的參數:
public class Demo1{Private static void do(MyFunctionalInterface inter){inter.myMethod();}public static void main(String[] args){do (() -> System.out.println("----"))} }2、常用函數接口
2、1.Supplier
java.util.function.Supplier 接?僅包含?個?參的?法: T get() 。?來獲取?個泛型參數 指定類型的對象數據。由于這是?個函數式接?,這也就意味著對應的Lambda表達式需要“對外提供”? 個符合泛型類型的對象數據。
實例:
import java.util.function.Supplier; public class Demo1{private static String getString(Supplier<String> function){return function.get();}public static void main(String[] args){String A = "aa";String B = "bb";System.out.println(getString(() -> A + B));} }2.2.Consumer
java.util.function.Consumer 接?則正好與Supplier接?相反,它不是?產?個數據,?是消費 ?個數據,其數據類型由泛型決定。
抽象方法:accept
Consumer 接?中包含抽象?法 void accept(T t) ,意為消費?個指定泛型的數據。基本使?如:
import java.util.function.Consumer; public class Demo1{private static void consumeString(Consumer<String> function){ function.accept("aa");}public static void main(String[] args){consumeString(s -> System.out.println(s));} }默認方法:andThen
如果?個?法的參數和返回值全都是 Consumer 類型,那么就可以實現效果:消費數據的時候,?先做? 個操作,然后再做?個操作,實現組合。?這個?法就是 Consumer 接?中的default?法 andThen 。 要想實現組合,需要兩個或多個Lambda表達式即可 。
2、3.Predicate
有時候我們需要對某種類型的數據進?判斷,從?得到?個boolean值結果。這時可以 使 java.util.function.Predicate 接?。
抽象方法:test
有時候我們需要對某種類型的數據進?判斷,從?得到?個boolean值結果。這時可以 使 java.util.function.Predicate 接?。
import java.util.function.Predicate; public class Demo15PredicateTest {private static void method(Predicate<String> predicate) {boolean veryLong = predicate.test("HelloWorld");System.out.println("字符串很?嗎:" + veryLong);}public static void main(String[] args) {method(s -> s.length() > 5);} } 默認方法:2.3.2、and:既然是條件判斷,就會存在與、或、?三種常?的邏輯關系。其中將兩個 Predicate 條件使?“與”邏輯連 接起來實現“并且”的效果時,可以使?default?法 and 。其JDK源碼為 ```java default Predicate<T> and(Predicate<? super T> other) {Objects.requireNonNull(other);return (t) -> test(t) && other.test(t); }2.3.3、or:
與 and 的“與”類似,默認?法 or 實現邏輯關系中的“或”。JDK源碼為:
default Predicate<T> or(Predicate<? super T> other) {Objects.requireNonNull(other);return (t) -> test(t) || other.test(t); }2.3.4、negate:
“與”、“或”已經了解了,剩下的“?”(取反)也會簡單。默認?法 negate 的JDK源代碼為:
default Predicate<T> negate() {return (t) -> !test(t); }ps:它是執?了test?法之后,對結果boolean值進?“!”取反?已。?定要在 test ?法 調?之前調? negate ?法,正如 and 和 or ?法?樣:
2、4.Function:
java.util.function.Function 接??來根據?個類型的數據得到另?個類型的數據,前者稱為 前置條件,后者稱為后置條件。
抽象?法:apply
Function 接?中最主要的抽象?法為: R apply(T t) ,根據類型T的參數獲取類型R的結果。 使?的場景例如:將 String 類型轉換為 Integer 類型。
import java.util.function.Function; public class Demo11FunctionApply {private static void method(Function<String, Integer> function) {int num = function.apply("10");System.out.println(num + 20);}public static void main(String[] args) {method(s -> Integer.parseInt(s));} }默認方法: andThen
Function 接?中有?個默認的 andThen ?法,?來進?組合操作。JDK源代碼如:
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {Objects.requireNonNull(after);return (T t) -> after.apply(apply(t)); }ps: 該?法同樣?于“先做什么,再做什么”的場景,和 Consumer 中的 andThen 差不多
二、Stream流
1.1獲取流的方法
java.util.stream.Stream 是Java 8新加?的最常?的流接?。(這并不是?個函數式接?。) 獲取?個流?常簡單,有以下?種常?的?式:
所有的 Collection 集合都可以通過 stream 默認?法獲取流;
Stream 接?的靜態?法 of 可以獲取數組對應的流。
import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Stream;public class Demo1 {public static void main(String[] args) {//獲得Stream對象//List獲得stream對象List <String> list = List.of("鄙人","張麻子","黃四郎");//快速生成集合,創建之后不可變Stream<String> stream = list.stream();//set獲得stream對象Set<String > set = Set.of("鄙人","張麻子","黃四郎");Stream<String> stream1 = set.stream();//Map獲得stream對象Map<String ,Integer>map = Map.of("鄙人",1,"張麻子",2,"黃四郎",3);Stream<String> stream2 = map.keySet().stream();Stream<Integer> stream3 = map.values().stream();Stream<Map.Entry<String, Integer>> stream4 = map.entrySet().stream();//數組獲得stream對象String [] strArr = {"鄙人","張麻子","黃四郎"};Stream<String> stream6 = Arrays.stream(strArr);Stream<Integer> stream5 = Stream.of(1,2,3,4,5);} }1、2.常用方法:
1.2.1:逐一處理:forEach
雖然?法名字叫 forEach ,但是與for循環中的“for-each”昵稱不同。
void forEach(Consumer<? super T> action);該?法接收?個 Consumer 接?函數,會將每?個流元素交給該函數進?處理。
實例:
import java.util.stream.Stream; public class Demo12StreamForEach {public static void main(String[] args) {Stream<String> stream = Stream.of("鄙人", "張麻子", "黃老爺");stream.forEach(name-> System.out.println(name));} }1.2.2:過濾:filter
可以通過 filter ?法將?個流轉換成另?個?集流。?法簽名:
Stream<T> filter(Predicate<? super T> predicate);該接?接收?個 Predicate 函數式接?參數(可以是?個Lambda或?法引?)作為篩選條件。
該?法將會產??個boolean值結果,代表指定的條件是否滿?。如果結果為true,那么Stream流的 filter ?法將會留?元素;如果結果為false,那么 filter ?法將會舍棄元素。
實例: 通過Lambda表達式來指定了篩選的條件:必須姓張。
import java.util.stream.Stream; public class Demo07StreamFilter {public static void main(String[] args) {Stream<String> original = Stream.of("張麻子", "黃四郎", "九筒");Stream<String> result = original.filter(s -> s.startsWith("張"));} }1.2.3:映射:map
如果需要將流中的元素映射到另?個流中,可以使? map ?法。?法簽名:
<R> Stream<R> map(Function<? super T, ? extends R> mapper);該接?需要?個 Function 函數式接?參數,可以將當前流中的T類型數據轉換為另?種R類型的流。
實例: map ?法的參數通過?法引?,將字符串類型轉換成為了int類型(并?動裝箱為 Integer類對象)。
import java.util.stream.Stream; public class Demo08StreamMap {public static void main(String[] args) {Stream<String> original = Stream.of("10", "12", "18");Stream<Integer> result = original.map(str->Integer.parseInt(str));} }1.2.4:統計個數:count
正如舊集合 Collection 當中的 size ?法?樣,流提供 count ?法來數?數其中的元素個數:
long count();該?法返回?個long值代表元素個數(不再像舊集合那樣是int值)。
import java.util.stream.Stream; public class Demo09StreamCount {public static void main(String[] args) {Stream<String> original = Stream.of("鄙人","張麻子","黃四郎");Stream<String> result = original.filter(s -> s.startsWith("張"));System.out.println(result.count()); // 2} }1.2.5: 取?前?個:limit
limit ?法可以對流進?截取,只取?前n個。?法簽名:
Stream<T> limit(long maxSize);參數是?個long型,如果集合當前?度?于參數則進?截取;否則不進?操作。基本使?:
import java.util.stream.Stream; public class Demo10StreamLimit {public static void main(String[] args) {Stream<String> original = Stream.of("鄙人","張麻子","黃四郎");Stream<String> result = original.limit(2);System.out.println(result.count()); // 2} }1.2.6: 跳過前?個:skip
如果希望跳過前?個元素,可以使? skip ?法獲取?個截取之后的新流:
Stream<T> skip(long n);如果流的當前?度?于n,則跳過前n個;否則將會得到?個?度為0的空流。基本使?:
import java.util.stream.Stream; public class Demo11StreamSkip {public static void main(String[] args) {Stream<String> original = Stream.of("鄙人","張麻子","黃四郎");Stream<String> result = original.skip(2);System.out.println(result.count()); // 1} }1.2.7: 組合:concat
如果有兩個流,希望合并成為?個流,那么可以使? Stream 接?的靜態?法 concat :
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) 實例: import java.util.stream.Stream; public class Demo12StreamConcat {public static void main(String[] args) {Stream<String> streamA = Stream.of("張麻子");Stream<String> streamB = Stream.of("張起靈");Stream<String> result = Stream.concat(streamA, streamB);} }1、3 小結練習
題? :現在有兩個 ArrayList 集合存儲隊伍當中的多個成員姓名,要求使?傳統的for循環(或增強for循環)依 次進?以下若?操作步驟:
第?個隊伍只要名字為3個字的成員姓名;存儲到?個新集合中。
第?個隊伍篩選之后只要前3個?;存儲到?個新集合中。
第?個隊伍只要姓張的成員姓名;存儲到?個新集合中。
第?個隊伍篩選之后不要前2個?;存儲到?個新集合中。
將兩個隊伍合并為?個隊伍;存儲到?個新集合中。
根據姓名創建 Person 對象;存儲到?個新集合中。
打印整個隊伍的Person對象信息。
package Stream;import java.util.ArrayList; import java.util.stream.Stream;public class Demo4 {public static void main(String[] args) {//第??隊伍ArrayList<String> one = new ArrayList<>();one.add("迪麗熱巴");one.add("宋遠橋");one.add("蘇星河");one.add("?破天");one.add("?中?");one.add("??");one.add("莊?");one.add("洪七公");//第??隊伍ArrayList<String> two = new ArrayList<>();two.add("古?娜扎");two.add("張?忌");two.add("趙麗穎");two.add("張三豐");two.add("尼古拉斯趙四");two.add("張天愛");two.add("張?狗");Stream<String> s1 = one.stream().filter(t -> t.length() == 3).limit(3);Stream<String> s2 = two.stream().filter(t -> t.startsWith("張")).skip(2);Stream<String> stream = Stream.concat(s1, s2);stream.map(name -> new Person(name)).forEach(p -> System.out.println(p ));} }總結
以上是生活随笔為你收集整理的JAVA基础---函数式接口、Stream流的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图片轮换-jQuery
- 下一篇: 解决Can't connect to l