- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) >
- JAVA8 lambda表達式權威教程
Java 8新特性----Stream流
jdk8是Java 語(yǔ)言開(kāi)發(fā)的一個(gè)主要版本,它支持函數式編程,新的 JavaScript 引擎,新的日期 API,新的Stream API 等等。今天就重點(diǎn)介紹一個(gè)非常重要得特性之一 lambda表達式
Stream(流)是一個(gè)來(lái)自數據源的元素隊列并支持聚合操作
Java中的Stream并不會(huì )存儲元素,而是按需計算。 數據源 流的來(lái)源。 可以是集合,數組,I/O channel, 產(chǎn)生器generator 等。
聚合操作 類(lèi)似SQL語(yǔ)句一樣的操作, 比如filter, map, reduce, find, match, sorted等。 和以前的Collection操作不同,Stream操作還有兩個(gè)基礎的特征如下:
(1)先產(chǎn)生一個(gè)流(Stream)一個(gè)數據源,獲取一個(gè)流。
(2)中間鏈式操作 一個(gè)中間的操作鏈,對數據源的數據進(jìn)行處理。
(3)產(chǎn)生一個(gè)新流:一個(gè)終止操作,執行中間操作,產(chǎn)生結果。
注意:Stream操作是延遲執行,他們會(huì )等需要結果的時(shí)候才會(huì )執行。
總結:
【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:通過(guò)Arrays中的Stream方法 數組 IntStream stream2 = Arrays.stream(new int[]{1, 2, 3, 4, 5}); //方式3:Stream中的of方法 Stream<String> stream3 = Stream.of("111", "222", "333"); //方法4:Stream中的方法 創(chuàng )建無(wú)限流 (結果是無(wú)線(xiàn)個(gè)) Stream<Integer> iterate = Stream.iterate(2, (x) -> x + 2);
1:篩選與切片
① Stream filter(Predicate<?super T> predicate)返回由與此給定謂詞匹配的此流的元素組成的流。 --->接收Lambda,從流中排除某些元素。
//1:創(chuàng )建Stream; Stream<Student> stream = list.stream(); //2:filter方法(找到年齡大于等于18歲的學(xué)生) Stream<Student> studentStream = stream.filter((student) -> student.getAge() >= 18); //3:終止操作;如果沒(méi)有終止操作的話(huà),上面的第二步中間操作不執行 studentStream.forEach(System.out::println); /** * 注意:如果值執行1,2操作的話(huà),不會(huì )有任何結果。 * 驗證出Steam操作是延遲的,只有進(jìn)行了終止操作,才會(huì )執行中間操作!這就是所謂的延遲加載 */
②Stream limit(Long maxSize) 返回由該流的元素組成的流,截斷長(cháng)度不能超過(guò)maxSize. 只有找到maxSize個(gè)滿(mǎn)足條件的即可。 ---->截斷流,使其元素不超過(guò)給定的數量。
public void limitTest02() { //Limit方法 短路(效率增高),只要找到了2個(gè)滿(mǎn)足條件的,后面的迭代操作就不在執行了! list.stream().filter(x -> { System.out.println("正在過(guò)濾??!"); return x.getAge() > 18; }).limit(2).forEach(System.out::println); }
③Stream skip(Long n) 在丟掉流的第一個(gè)n元素后,返回由該流的n元素組成的流,如果此流包含少于n元素,那么將返回一個(gè)空流。 ---->跳過(guò)元素,返回一個(gè)扔掉了前n個(gè)元素的流。 如果流中的元素不足n個(gè),則返回一個(gè)空流,與limit(n)互補。
public void skipTest03() { //skip 方法跳過(guò)前2個(gè)滿(mǎn)足條件的 留下后面滿(mǎn)足條件的結果??! list.stream().filter(x -> { System.out.println("正在過(guò)濾后面滿(mǎn)足條件的結果"); return x.getAge() > 18; }).skip(2).forEach(System.out::println); }
④Stream distinct()
注意: 自定義的類(lèi)在去重的過(guò)程中必須重新hashCode和equals方法,因為distinct實(shí)現的時(shí)候底層去找這兩個(gè)方法。
public void distinctTest04() { //distinct 去重操作! list.stream().distinct().forEach(System.out::println); }
⑤ map映射:
如果需要將流中的元素映射到另一個(gè)流中,可以使用map方法。方法簽名: Stream map(Function<? super T, ? extends R> mapper); 該接口需要一個(gè)Function函數式接口參數,可以將當前流中的T類(lèi)型數據轉換為另一種R類(lèi)型的流。 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方法的參數通過(guò)方法引用,將字符串類(lèi)型轉換成為了int類(lèi)型(并自動(dòng)裝箱為Integer類(lèi)對象)。
⑥ 排序 (兩種方式)
(1)Stream sorted()返回此流元素組成的流,根據自然順序排序。底層按照內部比較器進(jìn)行排序,實(shí)現Comparable接口中的compareTo方法。
(2)Stream sorted(Comparator<?super T>comparator) 返回由此元素組成的流,根據挺的Comparator進(jìn)行順序排序。指定順序。 指定排序策略:底層按照外部比較器進(jìn)行排序 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方法根據元素的自然順序排序,也可以指定比較器排序。
①查找(find)和匹配(match)
如果需要找到某些數據,可以使用find相關(guān)方法。方法簽名:
Stream流中的find相關(guān)方法使用代碼:
@Test public void testFind() { Optional<Integer> first = Stream.of(5, 3, 6, 1).findFirst(); System.out.println("first = " + first.get()); Optional<Integer> any = Stream.of(5, 3, 6, 1).findAny(); System.out.println("any = " + any.get()); }
Stream流的match方法
如果需要判斷數據是否匹配指定的條件,可以使用Match相關(guān)方法。方法簽名:
基本使用 Stream流中的Match相關(guān)方法使用代碼如:
@Test public void testMatch() { boolean b = Stream.of(5, 3, 6, 1) // .allMatch(e -> e > 0); // allMatch: 元素是否全部滿(mǎn)足條件 // .anyMatch(e -> e > 5); // anyMatch: 元素是否任意有一個(gè)滿(mǎn)足條件 .noneMatch(e -> e < 0); // noneMatch: 元素是否全部不滿(mǎn)足條件 System.out.println("b = " + b); }
②:遍歷 foreach
//forEach 用來(lái)遍歷流中的數據 @Test public void test02() { //案例1、2下面兩種寫(xiě)法等同 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.stream().mapToInt(String::length).min().getAsInt(); System.out.println("最長(cháng)字符的長(cháng)度:" + maxLines+",最短字符的長(cháng)度:"+minLines); //最長(cháng)字符的長(cháng)度:8,最短字符的長(cháng)度:4
④Stream流的count
// Stream流提供count方法來(lái)統計其中的元素個(gè)數:long count(); //該方法返回一個(gè)long值代表元素個(gè)數?;臼褂茫? @Test public void testCount() { List<String> strList = new ArrayList<>(); Collections.addAll(strList, "張無(wú)忌", "周芷若", "趙敏", "小昭", "楊不悔); System.out.println(strList.stream().count()); }
⑤ 分組:groupingBy;
當我們使用Stream流處理數據后,可以根據某個(gè)屬性將數據分組:
// 案例: @Test public void testGroup() { Stream<Student> studentStream = Stream.of( new Student("趙麗穎", 52, 95), new Student("楊穎", 56, 88), new Student("迪麗熱巴", 56, 55), new Student("柳巖", 52, 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='趙麗穎', age=52, socre=95}, Student{name='楊穎', age=56, socre=88}]
⑥拼接:joining
Collectors.joining會(huì )根據指定的連接符,將所有元素連接成一個(gè)字符串。 // 拼接 @Test public void testJoining() { Stream<Student> studentStream = Stream.of( new Student("趙麗穎", 52, 95), new Student("楊穎", 56, 88), new Student("迪麗熱巴", 56, 99), new Student("柳巖", 52, 77)); String collect = studentStream .map(Student::getName) .collect(Collectors.joining(">_<", "^_^", "^v^")); System.out.println(collect); }
效果:
^_^趙麗穎>_<楊穎>_<迪麗熱巴>_<柳巖^v^
⑦聚合:toList,toSet,toMap;
Stream流提供collect方法,其參數需要一個(gè)java.util.stream.Collector<T,A, R>接口對象來(lái)指定收集到哪種集合中。
下面是這兩個(gè)方法的基本使用代碼:
// 將流中數據收集到集合中 @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, 2, 3); Map<String, String> collect1 = list.stream().map(i -> i).collect(Collectors.toMap(key -> "key" + key, value -> "value:" + value)); //實(shí)體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表達式權威教程!的詳細內容,更多關(guān)于JAVA8 lambda表達式的資料請關(guān)注腳本之家其它相關(guān)文章!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。
Copyright ? 2009-2021 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 珠海市特網(wǎng)科技有限公司 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站