這麼簡單,還不會使用java8 stream流的map()方法嗎?

一、前言

在日常的開發工作中經常碰到要處理list中數據的問題,比如從數據庫中查出了很多學生,由於一些原因需要在內存中找出這些學生中的所有姓名,或者把名爲“王五”的語文成績暫時修改爲“100”,這些問題怎麼處理吶,之前我們想到的是遍歷每個元素,然後取出來放到另外一個集合中,在java8中對集合可以進行流式操作使上面的處理更簡潔。今天來看下map()方法的使用。

二、概述

stram流式處理中有map方法,先看下其定義,該方法在java.util.stream.Stream類中,

可以看到map()方法接收一個函數式接口參數,入參有一個T,返回一個Stream流,這個流是R泛型。主要有以下幾點注意,

  1. 入參是一個流中的元素;
  2. 出參是一個流,且流中是新元素;

用圖表示就是下面的樣子,原始流中有四個圓形圖案,調用map()函數後變成了四個五角星圖案,這裏的圓形圖案和五角星圖案是一一對應的,也就是原始流中有多少個元素,調用map()方法後依舊有多少個元素,唯一改變的是流中的元素類型

好了,下面看下怎麼使用map()函數。

三、詳述

以Student爲例,

Student.java

package com.example.log.stream.entity;
import java.io.Serializable;
/**
 * 學生類
 * @date 2022/11/30 20:40
 */
public class Student implements Serializable {
    /**
     * 姓名
     */
    private String name;
    /**
     * 班級
     */
    private String schoolClass;

    /**
     *語文成績
     */
    private Integer chineseScore;
    /**
     * 數學成績
     */
    private Integer MathScore;
    
    //省略get、set方法
}

有一個初始化數據的類,用來初始化一個List

Data.java

package com.example.log.stream.test;

import com.example.log.stream.entity.Student;

import java.util.ArrayList;
import java.util.List;

/**
 * @date 2022/11/30 22:43
 */
public class Data {
    public static List<Student> initData(){
        List<Student> students= new ArrayList<>();
        Student s1=new Student();
        s1.setName("王五");
        s1.setSchoolClass("一年級");
        s1.setChineseScore(100);
        s1.setMathScore(100);
        students.add(s1);

        Student s2=new Student();
        s2.setName("李四");
        s2.setSchoolClass("一年級");
        s2.setChineseScore(100);
        s2.setMathScore(100);
        students.add(s2);

        Student s3=new Student();
        s3.setName("李思");
        s3.setSchoolClass("二年級");
        s3.setChineseScore(100);
        s3.setMathScore(100);
        students.add(s3);

        Student s4=new Student();
        s4.setName("王五");
        s4.setSchoolClass("三年級");
        s4.setChineseScore(100);
        s4.setMathScore(100);
        students.add(s4);

        Student s5=new Student();
        s5.setName("趙三");
        s5.setSchoolClass("一年級");
        s5.setChineseScore(100);
        s5.setMathScore(100);
        students.add(s5);
        return students;
    }
}

下面根據上面的數據,進行下面的操作。

2.1、找出所有的學生姓名

TestMap.java

package com.example.log.stream.test;

import com.example.log.stream.entity.Student;

import java.util.ArrayList;
import java.util.List;

/**
 * 測試map方法
 * @date 2022/11/30 21:25
 */
public class TestMap {
    public static void main(String[] args) {
        List<Student> students=Data.initData();
        students.stream().map(student -> student.getName()).forEach(System.out::println);
    }

}

這裏使用了map()方法,入參是Student,出參是以String爲泛型的流,最後使用forEach進行了打印,看下結果

可以看到剛好把所有的學生姓名均打印出來了。如果想把這些學生姓名放到一個List中怎麼辦?

2.1.1、將學生姓名放到list中

package com.example.log.stream.test;

import com.example.log.stream.entity.Student;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 測試map方法
 *
 * @author wangcj5
 * @date 2022/11/30 21:25
 */
public class TestMap {
    public static void main(String[] args) {
        List<Student> students=Data.initData();
//        students.stream().map(student -> student.getName()).forEach(System.out::println);
        //將所有的學生姓名放到list中
        List<String> studentNames=students.stream().map(student -> student.getName()).collect(Collectors.toList());
     for (String studentName:studentNames) {
      System.out.println(studentName);
     }
    }
}

結果如下,

同樣的找出所有的班級,找出所有學生的成績都可類比上面的,可以看到打印出的學生姓名或班級是有重複數據,這個要怎麼解決。我們知道在最後是把數據放到list中,爲了解決重複的問題可以把數據放到set中,利用set的去重功能,

//將學生姓名放到Set中,可以實現去重功能
Set<String> studentNames=students.stream().map(student -> student.getName()).collect(Collectors.toSet());

結果不再打印,有興趣的可以自己試試。

2.2、將姓名爲“趙三”的語文成績置爲90

現在有這樣一個需求,要把姓名爲“趙三”學生的語文成績置爲90,看下利用map()函數怎麼做?

TestMap2.java

package com.example.log.stream.test;

import com.example.log.stream.entity.Student;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 測試map方法
 * @date 2022/11/30 21:25
 */
public class TestMap2 {
    public static void main(String[] args) {
        List<Student> students = Data.initData();

        List<Student> studentNames = students.stream().map(student -> {
            if ("趙三".equals(student.getName())) {
                student.setChineseScore(90);
            }
            return student;
        }).collect(Collectors.toList());

        for (Student studentName : studentNames) {
            System.out.println(studentName);
        }
        //打印老的list
        System.out.println("改之前的數據----------------");
        for (Student studentName : students) {
            System.out.println(studentName);
        }
    }
}

看下打印的結果 ,

從上面的結果中可以看出,”趙三“的語文成績的確被改爲了”90“,這點是沒錯的。再看原數據也被改爲了”90“,上面不是提到map()方法生成的是一個新流,原始流中的數據也被修改了,因爲下面這行代碼是在原始流中元素的基礎上修改的引用類型中的數據,導致的原始流中的數據也會改

map()方法的本意是不會對原始流中的元素造成影響,那麼只要new一個對象,返回即可了。現在想找出一年級學生的成績,用map()能實現嗎?

2.3、找出一年級學生的成績

試着去使用map()方法找出所有一年級學生的成績,發現無法實現,因爲map()方法強調原始流中的元素和新流中元素的個數要相同,或者理解爲一一對應,原始流中有5個學生,而要實現的目標流中一年級學生僅有3個,所以使用map()方法無法完成該功能。應該使用什麼方法,下期揭曉。

四、總結

java8的stream流map()方法是將流中的元素轉換爲另外一個流中的元素,轉換前後兩個流的元素個數不發生改變。

有不正之處,歡迎指正,謝謝!

感謝關注我的公衆號【良工說技術】,更多精彩。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章