您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“JAVA8中Stream的特性和使用”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
一、Stream的使用
1.1 創(chuàng)建
1.2 步驟
二、Stream的特性
三、中間操作
3.1 filter()
3.2 limit()
3.3 skip()
3.4 map()
3.5 sorted
四、終止操作
4.1 allMatch
4.2anyMatch
4.3noneMatch
4.4 findFirst()
4.5 findAny()
4.6 count
4.7 max
4.8 min
4.9 forEach
4.10 reduce
4.11 collect
通過(guò)Collection接口的實(shí)現(xiàn)類(lèi)提供的 stream()方法,或
通過(guò)Arrays中的靜態(tài)方法 stream()獲取
通過(guò)Stream類(lèi)中的靜態(tài)方法 of()
無(wú)限流(迭代/生成)
/** * @Author: 郜宇博 * @Date: 2021/9/1 23:28 * 流操作 */ public class StreamTests { @Test public void test(){ //1.通過(guò)Collection接口的實(shí)現(xiàn)類(lèi)提供的 stream()方法,或 Collection<String> list = new ArrayList<>(); list.stream(); list.parallelStream(); //2.通過(guò)Arrays中的靜態(tài)方法 stream()獲取 Integer[] integers = new Integer[10]; Arrays.stream(integers); //3.通過(guò)Stream類(lèi)中的靜態(tài)方法 of() Stream<String> stream = Stream.of("1","2"); //4.無(wú)限流 //迭代 Stream<Integer> iterate = Stream.iterate(0, (x) -> x + 2); //生成 Stream<Double> generate = Stream.generate(() -> Math.random()); } }
parallelStream提供了流的并行處理,它是Stream的另一重要特性,其底層使用Fork/Join框架實(shí)現(xiàn)。簡(jiǎn)單理解就是多線程異步任務(wù)的一種實(shí)現(xiàn)。
創(chuàng)建Stream;
轉(zhuǎn)換Stream,每次轉(zhuǎn)換原有Stream對(duì)象不改變,返回一個(gè)新的Stream對(duì)象(可以有多次轉(zhuǎn)換);
對(duì)Stream進(jìn)行聚合(Reduce)操作,獲取想要的結(jié)果;
惰性求值:
多個(gè)中間操作
可以連接起來(lái)形成一個(gè)流水線,除非流水線上觸發(fā)終止操作,否則中間操作不會(huì)執(zhí)行任何處理!而是在終止操作時(shí)一次性全部處理,這種情況稱(chēng)為“惰性求值”。
篩選與切片
接受lambda表達(dá)式,從流中排除某些元素
@Test public void test2(){ //獲取一個(gè)數(shù)組 ArrayList<Integer> arrayList = new ArrayList<>(); for (int i = 0; i <10; i++) { arrayList.add(i); } //流操作:獲取大于5的 arrayList.stream().filter((num)->num>5).forEach(System.out::println); } //結(jié)果: 6 7 8 9
截?cái)嗔鳎蛊湓貍€(gè)數(shù)不超過(guò)一定數(shù)量
滿足limit的數(shù)量后,就短路,不在執(zhí)行后續(xù)操作
@Test public void test2(){ //獲取一個(gè)數(shù)組 ArrayList<Integer> arrayList = new ArrayList<>(); for (int i = 0; i <10; i++) { arrayList.add(i); } //流操作:獲取大于5的 arrayList.stream().filter((num)->num>5) .limit(2) .forEach(System.out::println); } //結(jié)果: 6 7
跳過(guò)元素,跳過(guò)前n個(gè)元素,執(zhí)行后面的元素,如果不足n個(gè)則返回空流
@Test public void test2(){ //獲取一個(gè)數(shù)組 ArrayList<Integer> arrayList = new ArrayList<>(); for (int i = 0; i <10; i++) { arrayList.add(i); } //流操作:獲取大于5的 arrayList.stream().filter((num)->num>5) .skip(2) .forEach(System.out::println); } //結(jié)果: 8 9 3.3 map() 映射,在方法中使用方法Function< T> 函數(shù)型接口 -----> R apply(T t); @Test public void test4(){ //獲取一個(gè)list List<String> list = Arrays.asList("aaa","bbb","ccc"); //使用流操作 轉(zhuǎn)化大寫(xiě) list.stream().map((str)->str.toUpperCase()) .forEach(System.out::println); } /*結(jié)果:AAA BBB CCC*/ @Test public void test3(){ //獲取一個(gè)list List<String> list = Arrays.asList("aaa","bbb","ccc"); //流操作: 將list中的元素取出 //第一步使用map取出流,流里存放的還是流 //因此需要二次foreach Stream<Stream<Character>> chs = list.stream().map(StreamTests::getUpper); chs.forEach((stream)->{ stream.forEach(System.out::print); }); } //將str返回為流對(duì)象 public static Stream<Character> getUpper(String str){ List<Character> list = new ArrayList<>(); for (Character character: str.toCharArray()){ list.add(character); } return list.stream(); } //結(jié)果:aaabbbccc
映射,在方法中使用方法Function< T> 函數(shù)型接口 -----> R apply(T t);
@Test public void test4(){ //獲取一個(gè)list List<String> list = Arrays.asList("aaa","bbb","ccc"); //使用流操作 轉(zhuǎn)化大寫(xiě) list.stream().map((str)->str.toUpperCase()) .forEach(System.out::println); } /*結(jié)果:AAA BBB CCC*/
@Test public void test3(){ //獲取一個(gè)list List<String> list = Arrays.asList("aaa","bbb","ccc"); //流操作: 將list中的元素取出 //第一步使用map取出流,流里存放的還是流 //因此需要二次foreach Stream<Stream<Character>> chs = list.stream().map(StreamTests::getUpper); chs.forEach((stream)->{ stream.forEach(System.out::print); }); } //將str返回為流對(duì)象 public static Stream<Character> getUpper(String str){ List<Character> list = new ArrayList<>(); for (Character character: str.toCharArray()){ list.add(character); } return list.stream(); } //結(jié)果:aaabbbccc
相當(dāng)于集合方法的 addAll
即:將流中的流內(nèi)元素取出,放入一個(gè)流中,而不是流內(nèi)套流
@Test public void test3(){ //獲取一個(gè)list List<String> list = Arrays.asList("aaa","bbb","ccc"); //流操作: 將list中的元素取出 //第一步使用map取出流,流里存放的還是流 //因此需要二次foreach Stream<Stream<Character>> chs = list.stream().map(StreamTests::getUpper); chs.forEach((stream)-> stream.forEach(System.out::print)); System.out.println("\n====="); //方法二: //使用flatMap list.stream().flatMap(StreamTests::getUpper).forEach(System.out::print); }
@Test public void test5(){ List<String> list = Arrays.asList("aaa", "ccc", "bbbb", "eeeee"); //自然排序 list.stream() .sorted() .forEach(System.out::println); System.out.println("============="); //定制排序 list.stream() .sorted((x,y)->{ //如果長(zhǎng)度一樣,則按照字典排序 if (x.length() == y.length()){ return x.compareTo(y); } //如果長(zhǎng)度不一樣則按照長(zhǎng)度的降序排序 else { return y.length() - x.length(); } }) .forEach(System.out::println); } /*結(jié)果: aaa bbbb ccc eeeee ============= eeeee bbbb aaa ccc */
查找與匹配
Predicate<? super T> predicate /** * @Author: 郜宇博 * @Date: 2021/9/3 14:00 * 終止操作 */ public class FinalOperation { static ArrayList<Student> list; /** * allMath 檢查是否全部元素符合 */ @BeforeEach public void before(){ //準(zhǔn)備集合 Student student1 = new Student(10,"張三", Student.Status.Sad); Student student2 = new Student(20,"李四", Student.Status.Happy); Student student3 = new Student(30,"王五", Student.Status.Free); Student student4 = new Student(18,"田七", Student.Status.Free); Student student5 = new Student(140,"趙六", Student.Status.Tired); list = new ArrayList<>(); list.add(student1); list.add(student2); list.add(student3); list.add(student4); list.add(student5); } } class Student{ private int age; private String name; private Status status; public int getAge() { return age; } public String getName() { return name; } public Status getStatus() { return status; } /** * 枚舉狀態(tài) */ public enum Status{ Free,Tired,Happy,Sad; } public Student(int age, String name, Status status) { this.age = age; this.name = name; this.status = status; } } /** * 是否全部年齡都大于20 */ @Test public void test1(){ boolean b = list.stream().allMatch((s) -> s.getAge() > 20); System.out.println(b); } //結(jié)果: false
Predicate<? super T> predicate /** * 是否存在年齡大于20的 */ @Test public void test2(){ boolean b = list.stream().anyMatch((s) -> s.getAge() > 20); System.out.println(b); } //結(jié)果:true
Predicate<? super T> predicate /** * 是否沒(méi)有滿足年齡大于20的 * */ @Test public void test3(){ boolean b = list.stream().noneMatch((s) -> s.getAge() > 20); System.out.println(b); } //結(jié)果:false
返回第一元素,但結(jié)果可能為null, 因此使用Optional<T> 來(lái)接收,如果為null則可以替換。
/** * 返回第一元素 */ @Test public void test4(){ Optional<Student> first = list.stream() .filter((e) -> e.getStatus().equals(Student.Status.Free)) .findFirst(); System.out.println(first); } //結(jié)果:Optional[Student{age=30, name='王五', status=Free}]
返回任意一個(gè)
/** * 返回任意一個(gè) * */ @Test public void test5(){ Optional<Student> b = list.parallelStream() .filter((student -> student.getAge()<30)) .findAny(); System.out.println(b.get()); } //結(jié)果: 任意一個(gè)年齡小于30的學(xué)生
/** * 獲取數(shù)量count */ @Test public void test6(){ long count = list.stream().count(); System.out.println(count); } //結(jié)果 : 5
/** * 獲得最大值 */ @Test public void test7(){ Optional<Integer> max = list.stream() .map(x->x.getAge()) .max(Integer::compare); System.out.println(max.get()); } //結(jié)果: 140
/** * 獲得最小值 */ @Test public void test7(){ Optional<Integer> max = list.stream() .map(x->x.getAge()) .min(Integer::compare); System.out.println(max.get()); }
@Test public void test2(){ //獲取一個(gè)數(shù)組 ArrayList<Integer> arrayList = new ArrayList<>(); for (int i = 0; i <10; i++) { arrayList.add(i); } //流操作:獲取大于5的 arrayList.stream().filter((num)->num>5) .limit(2) .forEach(System.out::println); } //結(jié)果: 6 7
/** * 歸納 */ @Test public void test8(){ Integer reduce = list.stream() .map(Student::getAge) .reduce(0, (x, y) -> x + y); System.out.println(reduce); //方法二: //此方法有可能為null,因此封裝為Optional對(duì)象 Optional<Integer> reduce1 = list.stream() .map(Student::getAge) .reduce(Integer::sum); System.out.println(reduce1.get()); }
可以收集為集合類(lèi),
可以在收集后進(jìn)行分組、多級(jí)分組、分片
/** * 收集 */ @Test public void test9(){ List<Student> collect = list.stream().collect(Collectors.toList()); collect.forEach(System.out::println); //方式二: HashSet<Student> collect1 = list.stream().collect(Collectors.toCollection(HashSet::new)); collect.forEach(System.out::println); } /* 結(jié)果:Student{age=10, name='張三', status=Sad} Student{age=20, name='李四', status=Happy} Student{age=30, name='王五', status=Free} Student{age=18, name='田七', status=Free} Student{age=140, name='趙六', status=Tired} */ /** * 使用收集可以計(jì)算最大值、最小值、平均值、等 * 也可以進(jìn)行分組 */ @Test public void test10(){ Map<Student.Status, List<Student>> collect = list.stream().collect(Collectors.groupingBy((x) -> x.getStatus())); System.out.println(collect.size()); System.out.println(collect); }
“JAVA8中Stream的特性和使用”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。