當前位置: 妍妍網 > 碼農

流式方法:map操作、filter操作以及flatMap操作

2024-07-02碼農

大家好,我是磊哥。

關於stream 流式操作,在rt.jar 包裏面,ReferencePipeline管道方式運算元據 下面整合所有操作方法,利用這些流,處理大數據的方式,效率提升明顯,並且很多語言都支持這種操作,相當於統一了這種編程方式。

我們先來看看這三個操作過濾的是什麽數據,

過濾之後仍然可以迴圈數據
 list.stream().filter(smap -> null != smap.get("ip") && !"".equals(smap.get("ip"))).forEach(imp -> {
listipzone.add(wry.findIP(imp.get("ip").toString()));
});

1,filter操作,我們先看方法的定義

源碼如下 Stream filter(Predicate<? super T> predicate) ; 一個單純的過濾操作直接返回傳入型別

String[] dd = { "a", "b", "c" };
Stream stream = Arrays. stream (dd);
stream. filter (str -> str.equals("a")). forEach (System.out::println);//返回字串為a的值
2、 map操作,先看方法定義;

源碼如下 Stream map(Function<? super T, ? extends R> mapper);

這個方法傳入一個Function的函式式介面,這個介面,接收一個泛型T,返回泛型R,map函式的定義,返回的流,表示的泛型是R物件,這個表示,呼叫這個函式後,可以改變返回的型別

如果你近期準備面試跳槽,建議在ddkk.com線上刷題,涵蓋 一萬+ 道 Java 面試題,幾乎覆蓋了所有主流技術面試題,還有市面上最全的技術五百套,精品系列教程,免費提供。

publicstaticvoidmain(String[] args){
Integer[] dd = { 123 };
Stream<Integer> stream = Arrays.stream(dd);
stream.map(str -> Integer.toString(str)).forEach(str -> {
System.out.println(str);// 1 ,2 ,3
System.out.println(str.get class());// class java.lang.String
});
List<Emp> list = Arrays.asList(new Emp("a"), new Emp("b"), new Emp("c"));
list.stream().map(emp -> emp.getName()).forEach(str -> {
System.out.println(str);
});
 }
publicstatic classEmp{
private String name;
publicEmp(){
super();
}
publicEmp(String name){
super();
this.name = name;
}
public String getName(){
return name;
}
publicvoidsetName(String name){
this.name = name;
}
 }






可以看到,我們把Integer,變成了String輸出,把Emp物件裏的name字串,單獨輸出;現在,我們只看到了一個forEach的終端操作,後面,我們會看到,更多的終端操作,把map操作後,改變的物件型別,返回各種型別的集合,或者對數位型別的,返回求和,最大,最小等的操作;

3.flatMap操作,我們還是先看介面定義 包含前面兩種過濾型別

<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

這個介面,跟map一樣,接收一個Fucntion的函式式介面,不同的是,Function接收的泛型參數,第二個參數是一個Stream流;方法,返回的也是泛型R,具體的作用是把兩個流,變成一個流返回,下面,我們看一個案例,來詳細解答,怎麽把兩個流的內容,變成一個流的內容

publicstaticvoidmain(String[] args){
String[] strs = { "aaa""bbb""ccc" };
Arrays.stream(strs).map(str -> str.split("")).forEach(System.out::println);// Ljava.lang.String;@53d8d10a
Arrays.stream(strs).map(str -> str.split("")).flatMap(Arrays::stream).forEach(System.out::println);// aaabbbccc
Arrays.stream(strs).map(str -> str.split("")).flatMap(str -> Arrays.stream(str)).forEach(System.out::println);// aaabbbccc
 }

首先,第二段程式碼,才輸出的具體的字串;

第一段輸出程式碼裏,我們先看map操作,透過上面對map的介紹,我們可以看到,map可以改變返回的Stream的泛型,str.split(""),根據空字串分隔,返回的型別是一個陣列,**返回的流也是Stream<String[]>**,而不是Stream ;在第二段程式碼中,陣列的流,經過map操作,返回Stream<String[]>後,再經過flatMap,把陣列透過Arrays.stream變成一個新的流,再返回到原來的流裏;這樣,兩個流就合並成一個流;第三段程式碼,是第二段程式碼的,另一種寫法;

PS 簡單操作範例 1filter 過濾,2 map可以返回其它型別,3 flatMap合並兩個流數據

String[] includes=new String[10];
includeList.toArray(includes);
List<String> maplist = includeList.stream().map(s -> s.equals("a6")?"a6L":s).collect(Collectors.toList());
List<String> filterlist = includeList.stream().filter(s -> s.equals("a6")).collect(Collectors.toList());
includeList.stream().map(s -> s.equals("a6")?"a6L":s).forEach(System.out::println);//直接操作裏面的數據, 改變邏輯後可以返回list等
filterlist.forEach(System.out::println);// 只打印a6過濾的數據
maplist.forEach(System.out::println);

4構造流的幾種常見方法


Stream stream = Stream.of("a""b""c");
// 2. Arrays
String [] strArray = new String[] {"a""b""c"};
stream = Stream.of(strArray);
stream = Arrays.stream(strArray);
// 3. Collections
List<String> list = Arrays.asList(strArray);
stream = list.stream();
// map物件進行 排序對比,最主要還是要把數位轉化為 Integer型別去比較,否則只是字串比較,無意義,封裝成一個可比較的數據型別,轉化字串為數位型別 就可能排序了
model.put("data", listMap.stream()
.sorted((a, b) -> Integer.valueOf(b.get("count").toString()).compareTo(Integer.valueOf(a.get("count").toString())))






5 流轉換為其它數據結構

// 1. Array
String[] strArray1 = stream.toArray(String[]::new);
// 2. Collection
List<String> list1 = stream.collect(Collectors.toList());
List<String> list2 = stream.collect(Collectors.toCollection(ArrayList::new));
Set set1 = stream.collect(Collectors.toSet());
Stack stack1 = stream.collect(Collectors.toCollection(Stack::new));
// 3. String
String str = stream.collect(Collectors.joining()).toString();
//分組構造Map
Map<Integer, String> factoryMap = factoryConfigDOS.stream().collect( Collectors.groupingBy(AgencyDailySalaryFactoryConfigDO::getFenceId, Collectors.mapping(AgencyDailySalaryFactoryConfigDO::getFactoryName, joining(",")) ));
//Map轉化 函式運算式轉成MAP,key1和key2重復就覆蓋不然會報錯
Map nameMap = incumbentExcelInfoList.stream().collect(Collectors.toMap(info -> info.getIdCard(), info -> info.getName(),(key1,key2)->key2)); 

一個 Stream 只可以使用一次

很多API都有這種方式的操作,對後期大數據或者其它語言相容,解決跨語言的問題,也送出了效率,日後要以這種方式處理數據流的操作

如果你近期準備面試跳槽,建議在ddkk.com線上刷題,涵蓋 一萬+ 道 Java 面試題,幾乎覆蓋了所有主流技術面試題,還有市面上最全的技術五百套,精品系列教程,免費提供。

接下來,當把一個數據結構包裝成 Stream 後,就要開始對裏面的元素進行各類操作了。常見的操作可以歸類如下。
Intermediate: (中間)
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
Terminal:(終端)
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
Short-circuiting:(短路)
anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limi

limit/skip

limit 返回 Stream 的前面 n 個元素;skip 則是扔掉前 n 個元素(它是由一個叫 subStream 的方法改名而來)。

List<String> personList2 = persons.stream().
map(Person::getName).limit(10).skip(3).collect(Collectors.toList());
 System.out.println(personList2);

  • 所有 Stream 的操作必須以 lambda 運算式為參數

  • merge為Map介面新增的預設方法

    // k-8值存在為value8->執行merge函式->直接返回"NewMerge8"->newValue為"NewMerge8"
    // 執行put->所以這裏輸出"NewMerge8"
    map.merge(8"merge", (value, newValue) -> "NewMerge8");
    System.out.println(map.get(8));
    // 合並方式
    String newValue2 = map.merge(9"concat", (value, newValue) -> value.concat(newValue));
    // 解釋:從字串序列中過濾出以字元a開頭的字串並叠代打印輸出
    stringList.stream().filter((s) -> s.startsWith("a")).forEach(System.out::println);

    組合查詢 主要是peek 監視消費後執行的動作

    List<Integer> nums = Lists.newArrayList(1,1,null,2,3,4,null,5,6,7,8,9,10);
    System.out.println(「sum is:」+nums.stream().filter(num -> num != null).
    distinct().mapToInt(num -> num * 2).
    peek(System.out::println).skip(2).limit(4).sum());

    Integer型別的List,獲取其對應的Stream物件,然後進行過濾掉null,再去重,再每個元素乘以2,再每個元素被消費的時候打印自身,在跳過前兩個元素,最後去前四個元素進行加和運算

    7 數據並列化操作

    Stream 的並列化也是 Java 8 的一大亮點。數據並列化是指將數據分成塊,為每塊數據分配單獨的處理單元。這樣可以充分利用多核 CPU 的優勢。

    並列化操作流只需改變一個方法呼叫。如果已經有一個 Stream 物件,呼叫它的 parallel() 方法就能讓其擁有並列操作的能力。如果想從一個集合類建立一個流,呼叫 parallelStream() 就能立即獲得一個擁有並列能力的流。

    int sumSize = Stream.of("Apple""Banana""Orange""Pear") .parallel() .map(s -> s.length()) .reduce(Integer::sum) .get(); assertEquals(sumSize, 21);

    🔥 磊哥私藏精品 熱門推薦 🔥