<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## 42 常用的 Lambda 表達式使用場景解析和應用 ## 引導語 我們日常工作中,Lambda 使用比較多的場景,就是 List 或 Map 下的 Lambda 流操作,往往幾行代碼可以幫助我們實現多層 for 循環嵌套的復雜代碼,接下來我們把 Lambda 流的常用方法用案列講解一下。 ### 1 數據準備 本文演示的所有代碼都在 demo.eight.LambdaExpressionDemo 中,首先我們需要準備一些測試的數據,如下: ``` @Data // 學生數據結構 class StudentDTO implements Serializable { private static final long serialVersionUID = -7716352032236707189L; public StudentDTO() { } public StudentDTO(Long id, String code, String name, String sex, Double scope, List<Course> learningCources) { this.id = id; this.code = code; this.name = name; this.sex = sex; this.scope = scope; this.learningCources = learningCources; } /** * id */ private Long id; /** * 學號 唯一標識 */ private String code; /** * 學生名字 */ private String name; /** * 性別 */ private String sex; /** * 分數 */ private Double scope; /** * 要學習的課程 */ private List<Course> learningCources; } @Data // 課程數據結構 class Course implements Serializable { private static final long serialVersionUID = 2896201730223729591L; /** * 課程 ID */ private Long id; /** * 課程 name */ private String name; public Course(Long id, String name) { this.id = id; this.name = name; } } // 初始化數據 private final List<StudentDTO> students = new ArrayList<StudentDTO>(){ { // 添加學生數據 add(new StudentDTO(1L,"W199","小美","WM",100D,new ArrayList<Course>(){ { // 添加學生學習的課程 add(new Course(300L,"語文")); add(new Course(301L,"數學")); add(new Course(302L,"英語")); } })); add(new StudentDTO(2L,"W25","小美","WM",100D,Lists.newArrayList())); add(new StudentDTO(3L,"W3","小名","M",90D,new ArrayList<Course>(){ { add(new Course(300L,"語文")); add(new Course(304L,"體育")); } })); add(new StudentDTO(4L,"W1","小藍","M",10D,new ArrayList<Course>(){ { add(new Course(301L,"數學")); add(new Course(305L,"美術")); } })); } }; ``` 請大家稍微看下數據結構,不然看下面案例跑出來的結果會有些吃力。 ### 2 常用方法 #### 2.1 Filter Filter 為過濾的意思,只要滿足 Filter 表達式的數據就可以留下來,不滿足的數據被過濾掉,源碼如下圖: ![](https://img.kancloud.cn/06/cf/06cf54851512565d8c700c2289bd2374_2048x741.jpg) 我們寫了一個 demo,如下: ``` public void testFilter() { // list 在下圖中進行了初始化 List<String> newList = list.stream() // 過濾掉我們希望留下來的值 // StringUtils.equals(str,"hello") 表示我們希望字符串是 hello 能留下來 // 其他的過濾掉 .filter(str -> StringUtils.equals(str, "hello")) // Collectors.toList() 幫助我們構造最后的返回結果 .collect(Collectors.toList()); log.info("TestFilter result is {}", JSON.toJSONString(newList)); } ``` 運行結果如下: ![](https://img.kancloud.cn/05/46/0546784f41bda3402ae8c617d6b8b353_2252x840.jpg) #### 2.2 map map 方法可以讓我們進行一些流的轉化,比如原來流中的元素是 A,通過 map 操作,可以使返回的流中的元素是 B,源碼如下圖: ![](https://img.kancloud.cn/0d/06/0d06daa1a0d7d9caccc43ba8f2654208_2088x955.jpg) 我們寫了一個 demo,如下: ``` public void testMap() { // 得到所有學生的學號 // 這里 students.stream() 中的元素是 StudentDTO,通過 map 方法轉化成 String 的流 List<String> codes = students.stream() //StudentDTO::getCode 是 s->s.getCode() 的簡寫 .map(StudentDTO::getCode) .collect(Collectors.toList()); log.info("TestMap 所有學生的學號為 {}", JSON.toJSONString(codes)); } // 運行結果為:TestMap 所有學生的學號為 ["W199","W25","W3","W1"] ``` #### 2.3 mapToInt mapToInt 方法的功能和 map 方法一樣,只不過 mapToInt 返回的結果已經沒有泛型,已經明確是 int 類型的流了,源碼如下: ![](https://img.kancloud.cn/4e/7b/4e7b792663f47d91fd0452a0d595da75_1978x914.jpg) 我們寫了一個 demo,如下: ``` public void testMapToInt() { List<Integer> ids = students.stream() .mapToInt(s->Integer.valueOf(s.getId()+"")) // 一定要有 mapToObj,因為 mapToInt 返回的是 IntStream,因為已經確定是 int 類型了 // 所有沒有泛型的,而 Collectors.toList() 強制要求有泛型的流,所以需要使用 mapToObj // 方法返回有泛型的流 .mapToObj(s->s) .collect(Collectors.toList()); log.info("TestMapToInt result is {}", JSON.toJSONString(ids)); // 計算學生總分 Double sumScope = students.stream() .mapToDouble(s->s.getScope()) // DoubleStream/IntStream 有許多 sum(求和)、min(求最小值)、max(求最大值)、average(求平均值)等方法 .sum(); log.info("TestMapToInt 學生總分為: is {}", sumScope); } ``` 運行結果如下: ``` TestMapToInt result is [1,2,3,4] TestMapToInt 學生總分為: is 300.0 ``` #### 2.4 flatMap flatMap 方法也是可以做一些流的轉化,和 map 方法不同的是,其明確了 Function 函數的返回值的泛型是流,源碼如下: ![](https://img.kancloud.cn/8c/b8/8cb81f035266a5558e88d418e9d29e85_1558x441.jpg) 寫了一個 demo,如下: ``` public void testFlatMap(){ // 計算學生所有的學習課程,flatMap 返回 List<課程> 格式 List<Course> courses = students.stream().flatMap(s->s.getLearningCources().stream()) .collect(Collectors.toList()); log.info("TestMapToInt flatMap 計算學生的所有學習課程如下 {}", JSON.toJSONString(courses)); // 計算學生所有的學習課程,map 返回兩層課程嵌套格式 List<List<Course>> courses2 = students.stream().map(s->s.getLearningCources()) .collect(Collectors.toList()); log.info("TestMapToInt map 計算學生的所有學習課程如下 {}", JSON.toJSONString(courses2)); List<Stream<Course>> courses3 = students.stream().map(s->s.getLearningCources().stream()) .collect(Collectors.toList()); log.info("TestMapToInt map 計算學生的所有學習課程如下 {}", JSON.toJSONString(courses3)); } ``` 運行結果如下: ![](https://img.kancloud.cn/4a/3e/4a3e68ff6296f4842598e45c8701899e_1750x627.jpg) #### 2.5 distinct distinct 方法有去重的功能,我們寫了一個 demo,如下: ``` public void testDistinct(){ // 得到學生所有的名字,要求是去重過的 List<String> beforeNames = students.stream().map(StudentDTO::getName).collect(Collectors.toList()); log.info("TestDistinct 沒有去重前的學生名單 {}",JSON.toJSONString(beforeNames)); List<String> distinctNames = beforeNames.stream().distinct().collect(Collectors.toList()); log.info("TestDistinct 去重后的學生名單 {}",JSON.toJSONString(distinctNames)); // 連起來寫 List<String> names = students.stream() .map(StudentDTO::getName) .distinct() .collect(Collectors.toList()); log.info("TestDistinct 去重后的學生名單 {}",JSON.toJSONString(names)); } ``` 運行結果如下: ![](https://img.kancloud.cn/de/a0/dea04a75b78c7846c0ca9c925aa30cfa_1482x705.jpg) #### 2.6 Sorted Sorted 方法提供了排序的功能,并且允許我們自定義排序,demo 如下: ``` public void testSorted(){ // 學生按照學號排序 List<String> beforeCodes = students.stream().map(StudentDTO::getCode).collect(Collectors.toList()); log.info("TestSorted 按照學號排序之前 {}",JSON.toJSONString(beforeCodes)); List<String> sortedCodes = beforeCodes.stream().sorted().collect(Collectors.toList()); log.info("TestSorted 按照學號排序之后 is {}",JSON.toJSONString(sortedCodes)); // 直接連起來寫 List<String> codes = students.stream() .map(StudentDTO::getCode) // 等同于 .sorted(Comparator.naturalOrder()) 自然排序 .sorted() .collect(Collectors.toList()); log.info("TestSorted 自然排序 is {}",JSON.toJSONString(codes)); // 自定義排序器 List<String> codes2 = students.stream() .map(StudentDTO::getCode) // 反自然排序 .sorted(Comparator.reverseOrder()) .collect(Collectors.toList()); log.info("TestSorted 反自然排序 is {}",JSON.toJSONString(codes2)); } ``` 運行結果如下: ![](https://img.kancloud.cn/3d/eb/3deb7241f9f9bec364d22f1f837af9c0_1184x242.jpg) #### 2.7 peek peek 方法很簡單,我們在 peek 方法里面做任意沒有返回值的事情,比如打印日志,如下: ``` students.stream().map(StudentDTO::getCode) .peek(s -> log.info("當前循環的學號是{}",s)) .collect(Collectors.toList()); ``` #### 2.8 limit limit 方法會限制輸出值個數,入參是限制的個數大小,demo 如下: ``` public void testLimit(){ List<String> beforeCodes = students.stream().map(StudentDTO::getCode).collect(Collectors.toList()); log.info("TestLimit 限制之前學生的學號為 {}",JSON.toJSONString(beforeCodes)); List<String> limitCodes = beforeCodes.stream() .limit(2L) .collect(Collectors.toList()); log.info("TestLimit 限制最大限制 2 個學生的學號 {}",JSON.toJSONString(limitCodes)); // 直接連起來寫 List<String> codes = students.stream() .map(StudentDTO::getCode) .limit(2L) .collect(Collectors.toList()); log.info("TestLimit 限制最大限制 2 個學生的學號 {}",JSON.toJSONString(codes)); } ``` 輸出結果如下: ![](https://img.kancloud.cn/99/dc/99dc7618d3e4ab95691101b18013a57b_1307x222.jpg) #### 2.9 reduce reduce 方法允許我們在循環里面疊加計算值,我們寫了 demo 如下: ``` public void testReduce(){ // 計算一下學生的總分數 Double sum = students.stream() .map(StudentDTO::getScope) // scope1 和 scope2 表示循環中的前后兩個數 .reduce((scope1,scope2) -> scope1+scope2) .orElse(0D); log.info("總成績為 {}",sum); Double sum1 = students.stream() .map(StudentDTO::getScope) // 第一個參數表示成績的基數,會從 100 開始加 .reduce(100D,(scope1,scope2) -> scope1+scope2); log.info("總成績為 {}",sum1); } ``` 運行結果如下: ![](https://img.kancloud.cn/20/3a/203a5db6db9e5eadfc2066df9e9c1993_1045x665.jpg) 第二個計算出來的總成績多了 100,是因為第二個例子中 reduce 是從基數 100 開始累加的。 #### 2.10 findFirst findFirst 表示匹配到第一個滿足條件的值就返回,demo 如下: ``` // 找到第一個叫小美同學的 ID @Test public void testFindFirst(){ Long id = students.stream() .filter(s->StringUtils.equals(s.getName(),"小美")) // 同學中有兩個叫小美的,這里匹配到第一個就返回 .findFirst() .get().getId(); log.info("testFindFirst 小美同學的 ID {}",id); // 防止空指針 Long id2 = students.stream() .filter(s->StringUtils.equals(s.getName(),"小天")) .findFirst() // orElse 表示如果 findFirst 返回 null 的話,就返回 orElse 里的內容 .orElse(new StudentDTO()).getId(); log.info("testFindFirst 小天同學的 ID {}",id2); Optional<StudentDTO> student= students.stream() .filter(s->StringUtils.equals(s.getName(),"小天")) .findFirst(); // isPresent 為 true 的話,表示 value != null,即 student.get() != null if(student.isPresent()){ log.info("testFindFirst 小天同學的 ID {}",student.get().getId()); return; } log.info("testFindFirst 找不到名為小天的同學"); } ``` 運行結果如下: ![](https://img.kancloud.cn/a4/f7/a4f7888d1f31be35b074bede16148815_770x837.jpg) #### 2.11 groupingBy && toMap groupingBy 是能夠根據字段進行分組,toMap 是把 List 的數據格式轉化成 Map 的格式,我們寫了一個 demo,如下: ``` @Test public void testListToMap(){ // 學生根據名字進行分類 Map<String, List<StudentDTO>> map1 = students.stream() .collect(Collectors.groupingBy(StudentDTO::getName)); log.info("testListToMap groupingBy 學生根據名字進行分類 result is Map<String,List<StudentDTO>> {}", JSON.toJSONString(map1)); // 統計姓名重名的學生有哪些 Map<String, Set<String>> map2 = students.stream() .collect(Collectors.groupingBy(StudentDTO::getName, Collectors.mapping(StudentDTO::getCode,Collectors.toSet()))); log.info("testListToMap groupingBy 統計姓名重名結果 is {}", JSON.toJSONString(map2)); // 學生轉化成學號為 key 的 map Map<String, StudentDTO> map3 = students.stream() //第一個入參表示 map 中 key 的取值 //第二個入參表示 map 中 value 的取值 //第三個入參表示,如果前后的 key 是相同的,是覆蓋還是不覆蓋,(s1,s2)->s1 表示不覆蓋,(s1,s2)->s2 表示覆蓋 .collect(Collectors.toMap(s->s.getCode(),s->s,(s1,s2)->s1)); log.info("testListToMap groupingBy 學生轉化成學號為 key 的 map result is{}", JSON.toJSONString(map3)); } ``` 運行結果如下: ![](https://img.kancloud.cn/18/93/1893c0da0d42b986e5527d541554c838_1523x742.jpg) ### 3 總結 本文我們介紹了 12 種 Lambda 表達式常用的方法,大家可以找到 LambdaExpressionDemo 類,自己 debug 下,這樣你在工作中遇到復雜數據結構轉化時,肯定會得心應手了。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看