手把手帶你了解Java-Stream流方法學(xué)習(xí)及總結(jié)
前言
Stream是一個(gè)來自數(shù)據(jù)源的元素隊(duì)列并支持聚合操作,其中具有以下特性:
- Stream只負(fù)責(zé)計(jì)算,不存儲任何元素,元素是特定類型的對象,形成一個(gè)隊(duì)列
- 數(shù)據(jù)源可以實(shí)集合、數(shù)組、I/O channel、generator等
- 聚合操作有類似SQL的:filter、map、match、sorted等操作
- Stream流的執(zhí)行類似于懶加載,用戶使用時(shí)才執(zhí)行相應(yīng)操作
- 可消費(fèi)性;Stream只能被消費(fèi)一次,被消費(fèi)后需要重新生成
本文總結(jié)了部分在日常開發(fā)中經(jīng)常接觸到的一些Stream流相關(guān)的方法,不足之處或有錯(cuò)誤歡迎留評,總結(jié)的幾個(gè)方法如下:
- void forEach() : 迭代流中的數(shù)據(jù)
- Stream map() : 用于映射每個(gè)元素到對應(yīng)的結(jié)果
- Stream filter() : 條件過濾器
- Stream sorted() : 排序
- R collect() : 流數(shù)據(jù) -> 集合/數(shù)組
- 待補(bǔ)充…
forEach()
forEach()源碼:
void forEach(Consumer<!--? super T--> action);
Stream().forEach() : 迭代流中的數(shù)據(jù)
forEach() 的返回類型為void,不會產(chǎn)生新的流
舉個(gè)栗子:
public void testForEach() { /** * 使用forEach()內(nèi)部迭代 * ints()表示整數(shù)類型 * limit()表示限制流個(gè)數(shù)(次數(shù)) */ Random random = new Random(); random.ints().limit(10).forEach(System.out::println); }
運(yùn)行結(jié)果:
再舉個(gè)靈活一點(diǎn)的栗子:
public void testForEach() { /** * 使用forEach()轉(zhuǎn)換集合類型,如List->Map */ AtomicInteger i = new AtomicInteger();//原子類型 Map<Integer,String> map = new HashMap<>(); List<String> list = new ArrayList<>(Arrays.asList("Hello",",","world")); list.stream().forEach(s->{ map.put(i.getAndIncrement(),s); }); }
對于forEach()方法在本人日常開發(fā)中常用于:
- 使用內(nèi)循環(huán)對集合進(jìn)行遍歷
- 使用foreach方法將List轉(zhuǎn)為Map形式
map()
map()源碼:
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
Stream().map() 用于映射每個(gè)元素到對應(yīng)的結(jié)果
返回類型為Stream,map()會產(chǎn)生新的流并返回
舉個(gè)栗子:
public void testMap(){ /** * map()獲取list每個(gè)元素的平方值 * distinct()去重操作 * collect()將map()產(chǎn)生的新的流轉(zhuǎn)為List類型 */ List<Integer> list = Arrays.asList(1,2,3); list.stream().map(num -> num * num) .distinct() .collect(Collectors.toList()) .forEach(System.out::println); }
filter()
filter()源碼:
Stream<T> filter(Predicate<? super T> predicate);
Stream().filter()為條件過濾器
舉個(gè)栗子:
public void testFilter(){ /** * filter()過濾空字符串 * count()統(tǒng)計(jì)符合條件的個(gè)數(shù),返回類型long */ List<String> list = new ArrayList<>(Arrays.asList("ab","","abc","","acd")); long count = list.stream() .filter(str -> str.isEmpty()) .count(); }
sorted()
sorted()源碼:
Stream<T> sorted(); Stream<T> sorted(Comparator<? super T> comparator);
Stream支持兩種方式的排序:
無參方法默認(rèn)為自然排序sorted(Comparator comp) 按自定義比較器進(jìn)行排序
仍然是舉個(gè)栗子:
1)無參方法
public void testSorted(){ /** * sort()無參默認(rèn)為自然排序 * 返回類型Stream 會產(chǎn)生新的流 */ List<String> list = new ArrayList<>(Arrays.asList("aaa","ccc","bbb")); list.stream().sorted().forEach(System.out::println); }
執(zhí)行結(jié)果:
2)帶參方法(User類由name和age組成)
- 先比較年齡,按從小到大排序
- 若年齡相等,則按性名自然排序
public void testSorted(){ /** * sort(Comparator comp)按自定義比較器進(jìn)行排序 * 返回類型同樣是Stream 會產(chǎn)生新的流 */ List<User> userList = new ArrayList<>(Arrays.asList( new User("zhangsan",22), new User("wangwu",22), new User("badao",32), new User("kongfu",16) )); Stream<User> sorted = userList.stream().sorted((x, y) -> { if (x.getAge() == y.getAge()) { // 使用流中的序列兩兩進(jìn)行比較 return x.getName().compareTo(y.getName()); } else { return x.getAge() - y.getAge();//順序 // y.getAge() - x.getAge() 為逆序 } }); sorted.forEach(System.out::println); }
執(zhí)行結(jié)果:
collect()
collect()源碼:
<R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner);
stream().collect() 由三個(gè)參數(shù)構(gòu)成 :
1.Supplier 生產(chǎn)者,返回最終
2.結(jié)果BiConsumer<R, ? super T> accumulator,累加器 :
其中 R 為要返回的集合, ? super T 為遍歷過程中的每個(gè)參數(shù),相當(dāng)于add操作
3.BiConsumer<R,R> combiner,合并器 :
有并行流時(shí)才會使用,相當(dāng)于將第二部操作形成的list添加到最終的list,addAll操作
舉個(gè)栗子:
1)new()
public void testCollect(){ Stream<String> stream = Stream.of("hello","world","hello,world"); // new() List<String> list = stream.collect(Collectors.toList());//List // 指定集合類型,如ArrayList ArrayList<String> arrayList = stream.collect(Collectors.toCollection(ArrayList::new)); //Set stream.collect(Collectors.toSet()); // 指定HashSet HashSet<String> hashSet = stream.collect(Collectors.toCollection(HashSet::new)); // 拼接字符串 String str = stream.collect(Collectors.joining());
2)new() -> add() -> addAll()
public void testCollect(){ /** * 參數(shù)傳遞行為相當(dāng)于: new() -> add() -> addAll() */ Stream<String> stream = Stream.of("hello","world","hello,world"); // new() -> add() -> addAll()完整演示 HashMap<String,String> map = stream.collect(HashMap::new,(x,y)->{ x.put(y,y); // x 為集合,y 為當(dāng)前遍歷元素,以當(dāng)前遍歷元素作為kv },HashMap::putAll); map.forEach((x,y)->{ System.out.println(x+" : "+y); });
執(zhí)行結(jié)果:
總結(jié)
本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Java實(shí)現(xiàn)公眾號功能、關(guān)注及消息推送實(shí)例代碼
公眾號開發(fā)近些年是一個(gè)比較熱門的方向,下面這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)公眾號功能、關(guān)注及消息推送的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11Java基礎(chǔ)之JDBC的數(shù)據(jù)庫連接與基本操作
這篇文章主要介紹了Java基礎(chǔ)之JDBC的數(shù)據(jù)庫連接與基本操作,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java基礎(chǔ)的小伙伴們也有很好的幫助,需要的朋友可以參考下2021-05-05詳解springboot+atomikos+druid?數(shù)據(jù)庫連接失效分析
本文主要介紹了springboot+atomikos+druid?數(shù)據(jù)庫連接失效分析,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02MyBatis-Plus?實(shí)體類注解的實(shí)現(xiàn)示例
MyBatis-Plus作為MyBatis的增強(qiáng)版,提供了一系列實(shí)用的注解,如@TableName、@TableId、@TableField等,旨在簡化數(shù)據(jù)庫和Java實(shí)體類之間的映射及CRUD操作,通過這些注解,開發(fā)者可以輕松實(shí)現(xiàn)表映射、字段映射、邏輯刪除、自動(dòng)填充和樂觀鎖等功能2024-09-09SpringBoot項(xiàng)目構(gòu)建Maven標(biāo)簽及屬性用法詳解
在?Spring?Boot?項(xiàng)目中,Maven?是最常用的構(gòu)建工具之一,本文將詳細(xì)介紹?Maven?依賴管理中的主要標(biāo)簽及其使用方法,幫助開發(fā)者更好地理解和使用?Maven?構(gòu)建工具,感興趣的朋友跟隨小編一起看看吧2024-08-08SpringBoot預(yù)加載與懶加載實(shí)現(xiàn)方法超詳細(xì)講解
Spring一直被詬病啟動(dòng)時(shí)間慢,可Spring/SpringBoot是輕量級的框架。因?yàn)楫?dāng)Spring項(xiàng)目越來越大的時(shí)候,在啟動(dòng)時(shí)加載和初始化Bean就會變得越來越慢,很多時(shí)候我們在啟動(dòng)時(shí)并不需要加載全部的Bean,在調(diào)用時(shí)再加載就行,那這就需要預(yù)加載與懶加載的功能了2022-11-11