Stream是JDK8 API的新成員,它容許以聲明性方式處理數據集合java
實際開發中,項目中多數數據源都來自於MySQL,Oracle等.但如今數據源能夠更多了,有MongoDB,Redis等,而這些NoSQL的數據就須要Java層面去處理程序員
Stream和Collection集合的區別:Collection是一種靜態的內存數據結構,而Stream是有關計算的.前者是主要面向內存,存儲在內存中,後者主要是面向CPU,經過CPU實現計算編程
注意:
api
建立Stream數組
一個數據源(集合,數組等),獲取一個流markdown
中間操做數據結構
一箇中間操做鏈,對數據源的數據進行處理dom
終止操做ide
一旦執行終止操做,就執行中間操做鏈,併產生結果.以後,不會再被使用函數式編程
/** * @PROJECT_NAME: myTest * @DESCRIPTION: Stream的方法測試 * @USER: 羅龍達 * @DATE: 2021/2/21 2:33 */ public class streamTest { @Test public void createStream(){ List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jk"); //1. 經過集合建立stream -- 返回一個順序流 Stream<String> listStream = strings.stream(); //返回一個並行流 Stream<String> paraStream = strings.parallelStream(); //2. 經過數組建立stream IntStream arrStream = Arrays.stream(new int[]{1, 3, 45, 6, 877, 12}); //3. 經過Stream的of()方法 Stream<Integer> integerStream = Stream.of(1, 3, 5, 7, 9); //4. 建立無限流 Stream.iterate(0,t -> t+2).limit(10).forEach(System.out::println); //5. 生成 Stream.generate(Math::random).limit(10).forEach(System.out::println); } }
@Test public void InOperationTest() { List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "abc", "jk"); //1. 經過集合建立stream -- 返回一個順序流 Stream<String> listStream = strings.stream(); System.out.println("-----------測試filter--------------"); /** * filter(Predicate predicate) -- 接收lambda,從流中排除某些元素 * 查詢列表中不爲null的元素 */ // listStream.filter(s -> !s.equals("")).forEach(System.out::println); System.out.println("--------------測試limit------------"); /** *limit(n) -- 截斷流,使元素不超過給定數量 */ strings.stream().limit(3).forEach(System.out::println); System.out.println("-------------測試skip--------------"); /** *skip(n) -- 跳過元素,返回一個扔掉了前n個元素的流,若是流中元素不足n個,則返回一個空流 */ strings.stream().skip(3).forEach(System.out::println); System.out.println("------------測試distinct-----------"); /** *distinct() -- 篩選,經過流所產生元素的hashCode()和equals()去除重複元素 */ strings.stream().distinct().forEach(System.out::println); }
@Test public void mapTest(){ System.out.println("----------------將字符串轉換成大寫---------------"); List<String> strings = Arrays.asList("aaa", "bb", "cccc", "d","eeeee","ff"); /** * 接受一個函數做爲參數,將元素轉換成其餘形式或提取信息,該函數會被應用到每一個元素上,並將其映射成一個新的元素 */ strings.stream().map(String::toUpperCase).forEach(System.out::println); System.out.println("------------字符串長度大於3的元素的大寫-----------"); /** * 返回字符串長度大於3的元素的大寫 */ strings.stream().filter(s -> s.length() >3).map(String::toUpperCase).forEach(System.out::println); /** * flatMap(Function f) -- 接收一個函數做爲參數,將流中的每一個值都換成另外一個流,而後把全部流鏈接成一個流。 */ strings.stream().flatMap(streamTest::fromStringToStream).forEach(System.out::println); } //將字符串中的多個字符構成的集合轉換爲對應的流 public static Stream<Character> fromStringToStream(String s){ ArrayList<Character> list = new ArrayList<>(); for (char c : s.toCharArray()) { list.add(c); } return list.stream(); }
@Test public void sortTest() { List<Integer> list = Arrays.asList(23, 45, -12, 2, 7, 89, 5); System.out.println("----------從小到大排序測試---------"); list.stream().sorted().forEach(System.out::println); System.out.println("----------從大到小排序測試---------"); list.stream().sorted((i1, i2) -> i2 - i1).forEach(System.out::println); }
@Test public void termOperationTest(){ List<Integer> list = Arrays.asList(23, 45, -12, 2, 7, 89, 5); System.out.println("-----------allMatchTest-------------"); /** * allMatch(Predicate predicate) -- 檢查是否匹配全部元素 */ boolean allMatch = list.stream().allMatch(integer -> integer > 0); System.out.println(allMatch); System.out.println("-----------anyMatchTest-------------"); /** * allMatch(Predicate predicate) -- 檢查是否匹配全部元素 */ boolean anyMatch = list.stream().anyMatch(integer -> integer > 0); System.out.println(anyMatch); System.out.println("----------noneMatchTest-------------"); /** * noneMatch(Predicate predicate) -- 檢查是否沒有匹配的元素 */ boolean noneMatch = list.stream().noneMatch(integer -> integer > 0); System.out.println(noneMatch); System.out.println("----------findFirstTest-------------"); /** * findFirst() -- 返回流中第一個元素 */ Optional<Integer> first = list.stream().findFirst(); System.out.println(first); System.out.println("------------findAnyTest-------------"); /** * findAny() -- 返回流中任一元素 */ Optional<Integer> any = list.parallelStream().findAny(); System.out.println(any); System.out.println("--------------countTest-------------"); /** * count() -- 返回流中元素的總個數 */ long count = list.stream().filter(i -> i > 0).count(); System.out.println(count); System.out.println("------------max / min Test----------"); /** * max/min(Comparator comparator) -- 返回流中最大值 / 最小值 */ Optional<Integer> max = list.stream().max((i1, i2) -> i1 - i2); System.out.println("max = " + max); Optional<Integer> min = list.stream().min((i1, i2) -> i1 - i2); System.out.println("min = " + min); System.out.println("--------------forEachTest------------"); /** * forEach(Consumer c) -- 內部迭代 */ // list.stream().forEach(System.out::println); list.forEach(System.out::println); }
@Test public void reduceTest(){ List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); /** * reduce(T identity, BinaryOperator) -- 能夠將流中元素反覆結合起來,獲得一個值 */ Integer reduce = list.stream().reduce(0, Integer::sum); System.out.println("reduce = " + reduce); /** * reduce(BinaryOperator) -- 能夠將流中元素反覆結合起來,獲得一個值,返回optional */ Optional<Integer> reduce2 = list.stream().reduce(Integer::sum); Optional<Integer> reduce3 = list.stream().reduce((i1, i2) -> i1 + i2); System.out.println("reduce2 = " + reduce2); System.out.println("reduce3 = " + reduce3); }
@Test public void collectTest(){ List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); /** *collect(Collector c) 將流轉換爲其餘形式.接受一個Collector接口的實現 * 查找大於4的數字,結果返回一個list / set */ List<Integer> collectList = list.stream().filter(i -> i > 4).collect(Collectors.toList()); collectList.forEach(System.out::println); Set<Integer> collectSet = list.stream().filter(i -> i > 4).collect(Collectors.toSet()); collectSet.forEach(System.out::println); }
到目前爲止,臭名昭著的空指針異常是致使Java應用程序失敗的最多見緣由.
之前,爲了解決空指針異常,Google公司著名的Guava項目引入了Optional類,Guava經過使用檢查空值的方式來防止代碼污染,鼓勵程序員寫更乾淨的代碼.受到Google Guava的啓發,Optional類已經成爲Java 8 類庫的一部分
Optional
Optional類的Javadoc描述以下: 這是一個能夠爲null的容器對象.若是值存在在isPresent()方法會返回true,調用get()方法會返回該對象
# 1 建立Optional類對象的方法 - Optional.of(T t): 建立一個Optional實例,`t必須非空` - Optional.empty(): 建立一個空的Optional實例 - Optional.ofNullable(T t): t能夠爲null # 2 判斷Optional容器中是否包含對象: - boolean isPresent(): 判斷是否包含對象 - void ifPresent(Consumer consumer): 若是有值,就執行Consumer接口的實現代碼,而且該值會做爲參數傳給它 # 3 獲取Optional容器的對象 - T get(): 若是調用對象包含值,返回該值,不然拋異常 - T orElse(): 若是有值則將其返回,不然返回指定的other對象 - T orElseGet(Supplier other): 若是有值將其返回,不然返回由Supplier接口實現提供的對象 - T orElseThrow(Supplier exceptionSupplier): 若是有值則將其返回,不然拋出由Supplier接口實現提供的異常
public class Girl { public Girl() { } public Girl(String name) { this.name = name; } private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
public class Boy { private Girl girlFriend; private String name; public Boy() { } public Boy(Girl girlFriend, String name) { this.girlFriend = girlFriend; this.name = name; } public Girl getGirlFriend() { return girlFriend; } public void setGirlFriend(Girl girlFriend) { this.girlFriend = girlFriend; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
@Test public void OptionalTest(){ Girl girl = new Girl(); girl=null; Optional<Girl> optionalGirl = Optional.ofNullable(girl); System.out.println("optionalGirl = " + optionalGirl); } //原始的getName方法 public String getGirlName(Boy boy){ return boy.getGirlFriend().getName(); } //優化後的getName方法 public String getGirlNameAfterOptimizing(Boy boy){ Optional<Boy> boyOptional = Optional.ofNullable(boy); //此時boy1必定非空 Boy boy1 = boyOptional.orElse(new Boy(new Girl("楊冪"), "我")); Girl girlFriend = boy1.getGirlFriend(); Optional<Girl> girlFriend1 = Optional.ofNullable(girlFriend); //girlOption必定非空 Girl girlOptional = girlFriend1.orElse(new Girl("趙麗穎")); return "女友的名字 : " + girlOptional.getName(); } @Test public void testGetName(){ Boy boy = new Boy(); // boy = null; boy.setGirlFriend(null); // boy.setGirlFriend(new Girl("迪麗熱巴")); System.out.println(getGirlNameAfterOptimizing(boy)); }