JAVA8 lambda表示式權威教程
java 8新特性----Stream流
jdk8是Java 語言開發的一個主要版本,它支援函式式程式設計,新的 javascript 引擎,新的日期 API,新的Stream API 等等。今天就重點介紹一個非常重要得特性之一 lambda表示式
一:什麼是 Stream?
Stream(流)是一個來自資料來源的元素佇列並支援聚合操作
Java中的Stream並不會儲存元素,而是按需計算。 資料來源 流的來源。 可以是集合,陣列,I/O channel, 產生器generator 等。
聚合操作 類似SQL語句一樣的操作, 比如filter,map,reduce,find,match,sorted等。 和以前的Collection操作不同,Stream操作還有兩個基礎的特徵如下:
- Pipelining: 中間操作都會返回流物件本身。 這樣多個操作可以串聯成一個管道, 如同流式風格。 這樣做可以對操作進行優化, 比如延遲執行和短路。
- 內部迭代: 以前對集合遍歷都是通過Iterator或者For-Each的方式,顯式的在集合外部進行迭代, 這叫>做外部迭代。 Stream提供了內部迭代的方式, 通過訪問者模式(Visitor)實現。
二:Stream API 使用
1:使用Stream步驟:
(1)先產生一個流(Stream)一個數據源,獲取一個流。
(2)中間鏈式操作 一箇中間的操作鏈,對資料來源的資料進行處理。
(3)產生一個新流:一個終止操作,執行中間操作,產生結果。
注意:Stream操作是延遲執行,他們會等需要結果的時候才會執行。
總結:
- 中間操作常用方法有:篩選:filter 對映:map 排序:sorted提取與組合 收集:collect。
- 終止操作:遍歷:foreach 匹配:find、match 規約:reduce 聚合:max、min、count。
2:建立Stream的方法的4種方式
【1】Collection介面中的方法: default Stream<E> stream() 獲取序列流 default Stream<E> parallelStream() 獲取並行流 案例:
//方式1:Collection介面的方法 Collection collection = new ArrayList(); Stream stream = collection.stream(); Stream stream1 = collection.parallelStream(); //方式2:通過Arrays中的Stream方法 陣列 IntStream stream2 = Arrays.stream(new int[]{1,2,3,4,5});NBnKSZLBd //方式3:Stream中的of方法 Stream<String> stream3 = Stream.of("111","222","333"); //方法4:Stream中的方法 建立無限流 (結果是無線個) Stream<Integer> iterate = Stream.iterate(2,(x) -> x + 2);
3:中間操作
1:篩選與切片
① Stream filter(Predicate<?super T> predicate)返回由與此給定謂詞匹配的此流的元素組成的流。 --->接收Lambda,從流中排除某些元素。
//1:建立Stream; Stream<Student> stream = list.stream(); //2:filter方法(找到年齡大於等於18歲的學生) Stream<Student> studentStream = stream.filter((student) -> student.getAge() >= 18); //3:終止操作;如果沒有終止操作的話,上面的第二步中間操作不執行 studentStream.forEach(System.out::println); /** * 注意:如果值執行1,2操作的話,不會有任何結果。 * 驗證出Steam操作是延遲的,只有進行了終止操作,才會執行中間操作!這就是所謂的延遲載入 */
②Stream limit(Long maxSize) 返回由該流的元素組成的流,截斷長度不能超過maxSize. 只有找到maxSize個滿足條件的即可。 ---->截斷流,使其元素不超過給定的數量。
public void limitTest02() { //Limit方法 短路(效率增高),只要找到了2個滿足條件的,後面的迭代操作就不在執行了! list.stream().filter(x -> { System.out.println("正在過濾!!"); return x.getAge() > 18; }).limit(2).forEach(System.out::println); }
③Stream skip(Long n) 在丟掉流的第一個n元素後,返回由該流的n元素組成的流,如果此流包含少於n元素,那麼將返回一個空流。 ---->跳過元素,返回一個扔掉了前n個元素的流。 如果流中的元素不足n個,則返回一個空流,與limit(n)互補。
public void skipTest03() { //skip 方法跳過前2個滿足條件的 留下後面滿足條件的結果!! list.stream().filter(x -> { System.out.println("正在過濾後面滿足條件的結果"); return x.getAge() > 18; }).skip(2).forEach(System.out::println); }
④Stream distinct()
注意: 自定義的類在去重的過程中必須重新hashCode和equals方法,因為distinct實現的時候底層去找這兩個方法。
public void distinctTest04() { //distinct 去重操作! list.stream().distinct().forEach(System.out::println); }
⑤ map對映:
如果需要將流中的元素對映到另一個流中,可以使用map方法。方法簽名: Stream map(Function<? super T,? extends R> mapper); 該介面需要一個Function函式式介面引數,可以將當前流中的T型別資料轉換為另一種R型別的流。 Stream流中的map方法基本使用的程式碼如:
@Test public void testMap() { Stream<String> original = Stream.of("11","22","33"); Stream<Integer> result = original.map(Integer::parseInt); result.forEach(s -> System.out.println(s + 10)); } //這段程式碼中,map方法的引數通過方法引用,將字串型別轉換成為了int型別(並自動裝箱為Integer類物件)。
⑥ 排序 (兩種方式)
(1)Stream sorted()返回此流元素組成的流,根據自然順序排序。底層按照內部比較器進行排序,實現Comparable介面中的compareTo方法。
(2)Stream sorted(Comparator<?super T>comparator) 返回由此元素組成的流,根據挺的Comparator進行順序排序。指定順序。 指定排序策略:底層按照外部比較器進行排序 Comparator介面一定要重新Compare方法。
基本使用 Stream流中的sorted方法基本使用的程式碼如: @Test public void testSorted() { // sorted(): 根據元素的自然順序排序 // sorted(Comparator<? super T> comparator): 根據比較器指定的規則排序 Stream.of(33,22,11,55) .sorted() .sorted((o1,o2) -> o2 - o1) .forEach(System.out::println); } 這段程式碼中,sorted方法根據元素的自然順序排序,也可以指定比較器排序。
4:終止操作
①查詢(find)和匹配(match)
如果需要找到某些資料,可以使用find相關方法。方法簽名:
- Optional findFirst();
- Optional findAny();
Stream流中的find相關方法使用程式碼:
@Test public void testFind() { Optional<Integer> first = Stream.of(5,6,1).findFirst(); System.out.println("first = " + first.get()); Optional<Integer> any = Stream.of(5,1).findAny(); System.out.println("any = " + any.get()); }
Stream流的match方法
如果需要判斷資料是否匹配指定的條件,可以使用Match相關方法。方法簽名:
- boolean allMatch(Predicate<? super T> predicate);
- boolean anyMatch(Predicate<? super T> predicate);
- boolean noneMatch(Predicate<? super T> predicate);
基本使用 Stream流中的Match相關方法使用程式碼如:
@Test public void testMatch() { boolean b = Stream.of(5,1) // .allMatch(e -> e > 0); // allMatch: 元素是否全部滿足條件 // .anyMatch(e -> e > 5); // anyMatch: 元素是否任意有一個滿足條件 .noneMatch(e -> e < 0); // noneMatch: 元素是否全部不滿足條件 System.out.println("b = " + b); }
②:遍歷 foreach
//forEach 用來遍歷流中的資料 @Test public void test02() { //案例1、2下面兩種寫法等同 list.stream().map((x)->x.getName()).forEach(System.out::println); list.stream().map(Student::getName).forEach(System.out::println); }
③Stream流的max、min
List<String> list13 = Arrays.asList("zhangsan","lisi","wangwu","xuwujing");
int maxLines = list13.stream().mapToInt(String::length).max().getAsInt();
int minLines = list13.swww.cppcns.comtream().mapToInt(String::length).min().getAsInt();
System.out.println("最長字元的長度:" + maxLines+",最短字元的長度:"+minLines);
//最長字元的長度:8,最短字元的長度:4
④Stream流的chttp://www.cppcns.comount
// Stream流提供count方法來統計http://www.cppcns.com其中的元素個數:long count(); //該方法返回一個long值代表元素個數。基本使用: @Test public void testCount() { List<String> strList = new ArrayList<>(); Collections.addAll(strList,"張無忌","周芷若","趙敏","小昭","楊不悔); System.out.println(strList.stream().count()); }
⑤ 分組:groupingBy;
當我們使用Stream流處理資料後,可以根據某個屬性將資料分組:
// 案例: @Test public void testGroup() { Stream<Student> studentStream = Stream.of( new Student("趙麗穎",52,95),new Student("楊穎",56,88),new Student("迪麗熱巴",55),new Student("柳巖",33)); // Map<Integer,List<Student>> map = studentStream.collect(Collectors.groupingBy(Student::getAge)); // 將分數大於60的分為一組,小於60分成另一組 Map<String,List<Student>> map = studentStream.collect(Collectors.groupingBy((s) -> { if (s.getSocre() > 60) { return "及格"; } else { return "不及格"; } })); map.forEach((k,v) -> { System.out.println(k + "::" + v); }); }
效果: 不及格::[Student{name='迪麗熱巴',age=56,socre=55},Student{name='柳巖',age=52,socre=33}] 及格::[Student{name='趙麗穎',socre=95},Student{name='楊穎',socre=88}]
⑥拼接:joining
Collectors.joining會根據指定的連線符,將所有元素連線成一個字串。 // 拼接 @Test public void testJoining() { Stream<Student> studentStream = Stream.of( new Student("趙麗穎",99),77)); String collect = studentStream .map(Student::getName) .collect(Collectors.joining(">_<","^_^","^v^")); System.out.println(collect); }
效果:
^_^趙麗穎>_<楊穎>_<迪麗熱巴>_<柳巖^v^
⑦聚合:toList,toSet,toMap;
Stream流提供collect方法,其引數需要一個java.util.stream.Collector<T,A,R>介面物件來指定收集到哪種集合中。
- public static Collector<T,?,List> toList():轉換為List集合。
- public static Collector<T,Set> toSet():轉換為Set集合。
- public static <T,K,U> Collector<T,Map<K,U>> toMap(Function<? super T,? extends程式設計客棧 K> keyMapper,Function<? super T,? extends U> valueMapper):轉換為Map集合。
下面是這兩個方法的基本使用程式碼:
// 將流中資料收集到集合中 @Test public void testStreamToCollection() { Stream<String> stream = Stream.of("aa","bb","cc"); // List<String> strList = stream.collect(Collectors.toList()); // Set<String> strSet = stream.collect(Collectors.toSet()); ArrayList<String> arrayList = stream.collect(Collectors.toCollection(ArrayList::new)); HashSet<String> hashSet = stream.collect(Collectors.toCollection(HashSet::new)); }
toMap
@Test public void testCollectToMap(){ //案例1 List<Integer> list = Arrays.asList(1,3); Map<String,String> collect1 = list.stream().map(i -> i).collect(Collectors.toMap(key -> "key" + key,value -> "value:" + value)); //實體list轉化map id作為主鍵,物件作為value List<User> userList =new ArrayList<User>(); UserTask userTask = new UserTask(); userTask.setId(1); userTask.setName("測試"); userList.add(userTask); Map<Integer,UserTask> taskMap = userList.stream().collect(Collectors.toMap(UserTask::getId,entity -> entity)); System.out.println(collect1.toString()); System.out.println(taskMap.toString()); }
以上就是JAVA8 lambda表示式權威教程!的詳細內容,更多關於JAVA8 lambda表示式的資料請關注我們其它相關文章!