[Lambda] Lambda expressions for collections

[1] Introduction to the method of Stream

[1] Commonly used methods in Stream

(1) collect(toList()): generate a list through Stream
(2) map: convert a value in the stream into a new value
(3) filter: filter the elements in the Stream
(4) flatMap: convert multiple Stream is connected into a Stream
(5) max: find the maximum value
(6) min: find the minimum value
(7) reduce: generate a new value from a set of values
​​(8) Collectors.joining: take out a value from a set of values Do splicing (can replace String.join method)

【2】collect(toList()) & filter

The function of collect(toList()) is to generate a List object through a Stream object, case:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> result = list.stream().filter((value) -> value > 2).collect(toList());
result.forEach((value) -> System.out.print(value));

The above code first creates a List object and initializes it, then filters out the values ​​greater than 2 and outputs it.
The function of the filter method is to filter the elements in the Stream. The filter method is a high-order function that receives a function interface as a parameter. This high-order function returns a boolean value, and the elements that return true will be retained; collect(toList())
method Generate a List from the Stream returned by the filter operation.

【3】map

When operating on a collection, we often selectively extract the value of certain elements from certain objects, just like writing SQL, specifying to obtain a specific data column in the table. The function of the map function is to convert one of the
streams The value is converted into a new value. For example, if we want to convert a List into a List, then we can use the map method. Sample code:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<String> result = list.stream().map(value -> String.format("String:%s", value)).collect(toList());
result.forEach(System.out::print);

The map method converts Integer elements into String and uses the collect(toList()) method to generate a new List.

System.out::print is a shorthand for (value) -> System.out.print(value).

【4】flatMap

flatMap: connect multiple Streams into one Stream, how to understand this, give a chestnut:
first define a List object, divide each String in this object into a letter and generate a new List object, code:

List<String> list = Arrays.asList("abc", "def", "ghi");
List<Character> result = list.stream().flatMap(value -> {
    
    
    char[] chars = value.toCharArray();
    Character[] characters = new Character[chars.length];
    for(int i = 0; i < characters.length; i++){
    
    
        characters[i] = chars[i];
    }
    return Stream.of(characters);
}).collect(toList());
result.forEach(System.out::println);

The above code first traverses the list, generates a new Stream for each String element through the flatMap function, and connects these Streams into a new Stream.

【5】max&min

Find the maximum and minimum

List<Integer> list = Arrays.asList(0, 1, 2, 3);
Comparator<Integer> comparator = (o1, o2) -> o1.compareTo(o2);
System.out.println(list.stream().min(comparator).get());
System.out.println(list.stream().max(comparator).get());

The min and max functions require a Comparator object as a parameter for comparison.

【6】reduce

Generate a new value from a set of values. The reduce function is actually very versatile and powerful. Let’s give an example of accumulation:

List<Integer> list = Arrays.asList(0, 1, 2, 3);
int count = list.stream().reduce(0, (acc, item) -> acc + item).intValue();
System.out.println(count);

One parameter of the reduce function is the initial value of the loop, where the initial value is 0 when calculating the accumulation, acc represents the calculated result, and item represents each element of the loop.

List<Integer> integers = Arrays.asList(1, 2, 3, 4, 4, 5, 5, 6, 7, 8, 2, 2, 2, 2);
Integer reduce = integers.stream().reduce(0, (integer1, integer2) -> integer1 + integer2);
System.out.println(reduce);

In the above code, the first parameter in reduce is declared as the initial value, and the second parameter receives a lambda expression representing two elements in the current stream, which will repeatedly add each element until the stream is returned to a final result

Integer reduce = integers.stream().reduce(0,Integer::sum);

It can be optimized like this. Of course, reduce also has an overloaded method without an initial value parameter, but it is necessary to judge the return result, because if there are no elements in the stream, there may be no result. The specific method is as follows

【7】ifPresent

[8] findAny: find elements

For set operations, it is sometimes necessary to find elements that meet the conditions in the set. Stream also provides related APIs, findAny() and findFirst(), which can be used in combination with other stream operations. findAny is used to obtain a random element in the stream, and findFirst is used to obtain the first element in the stream. As for some special customization requirements, you need to implement them yourself.

findAny is used to obtain a random element in the stream, and use the short circuit to end immediately when the result is found

//findAny用于获取流中随机的某一个元素,并且利用短路在找到结果时,立即结束
ArrayList<Student> students = new ArrayList<>();
students.add(new Student(1,19,"张三1","M",true));
students.add(new Student(1,18,"张三2","M",false));
students.add(new Student(1,21,"张三3","F",true));
students.add(new Student(1,20,"张三4","F",false));
students.add(new Student(1,20,"张三5","F",false));
students.add(new Student(1,20,"张三6","F",false));
Optional<Student> student1 = students.stream().filter(student -> student.getSex().equals("F")).findAny();
System.out.println(student1.toString());

【9】findFirst:

[9] anyMatch: Judgment condition matches at least one element

anyMatch() is mainly used to determine whether there is at least one eligible element in the stream, it will return a boolean value, and its operation is generally called short-circuit evaluation

Determine whether there are students younger than 20 in the collection

//判断集合中是否有年龄小于20的学生
ArrayList<Student> students = new ArrayList<>();
students.add(new Student(1,19,"张三","M",true));
students.add(new Student(1,18,"李四","M",false));
students.add(new Student(1,21,"王五","F",true));
students.add(new Student(1,20,"赵六","F",false));

if(students.stream().anyMatch(student -> student.getAge() < 20)){
    
    
    System.out.println("集合中有年龄小于20的学生");
}else {
    
    
    System.out.println("集合中没有年龄小于20的学生");
}

【10】allMatch: Determine whether the condition matches all elements

The working principle of allMatch() is similar to anyMatch(), but when anyMatch is executed, as long as there is an element in the stream that meets the conditions, it will return true, and allMatch will judge whether all the conditions in the stream meet the conditions, and all of them will return true

Determine whether the age of all students in the set is less than 20

//判断集合所有学生的年龄是否都小于20
ArrayList<Student> students = new ArrayList<>();
students.add(new Student(1,19,"张三","M",true));
students.add(new Student(1,18,"李四","M",false));
students.add(new Student(1,21,"王五","F",true));
students.add(new Student(1,20,"赵六","F",false));

if(students.stream().allMatch(student -> student.getAge() < 20)){
    
    
    System.out.println("集合所有学生的年龄都小于20");
}else {
    
    
    System.out.println("集合中有年龄大于20的学生");
}

[11] skip: skip

Intercept 5 data from the third one in the collection

//从集合第三个开始截取5个数据
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 4, 5, 5, 6, 7, 8, 2, 2, 2, 2);
List<Integer> collect = integers.stream().skip(3).limit(5).collect(Collectors.toList());
collect.forEach(integer -> System.out.print(integer+" "));

First intercept 5 elements from the collection, and then take the last 3

//先从集合中截取5个元素,然后取后3个
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 4, 5, 5, 6, 7, 8, 2, 2, 2, 2);
List<Integer> collect = integers.stream().limit(5).skip(2).collect(Collectors.toList());
collect.forEach(integer -> System.out.print(integer+" "));

[12] distinct: deduplication

List<Integer> integers = Arrays.asList(1, 2, 3, 4, 4, 5, 5, 6, 7, 8, 2, 2, 2, 2);
integers.stream().distinct().collect(Collectors.toList());

[13] limit: slice

Get the first five digits of the array

//获取数组的前五位
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 4, 5, 5, 6, 7, 8, 2, 2, 2, 2);
integers.stream().limit(5);

[14] filter: filter

Get all students under the age of 20

public class FilterDemo {
    
    
    public static void main(String[] args) {
    
    
        
        //获取所有年龄20岁以下的学生
        ArrayList<Student> students = new ArrayList<>();
        students.add(new Student(1,19,"张三","M",true));
        students.add(new Student(1,18,"李四","M",false));
        students.add(new Student(1,21,"王五","F",true));
        students.add(new Student(1,20,"赵六","F",false));
        students.stream().filter(student -> student.getAge()<20);
    }
}

[2] Summary of Common Cases

【1】Preparation method to query the database to obtain the List result

I use the mapper of Mybatis-plus, or I can customize a List collection by myself

@SpringBootTest
public class LambdaTest {
    
    
    @Autowired
    private UserMapper userMapper;

    @Test
    public void selectList() {
    
    
        // 通过条件构造器查询一个List集合,如果没有条件,就可以设置null为参数
        List<User> list = userMapper.selectList(null);
        list.forEach(System.out::println);
    }
}

Entity class code is

@Data // 包含以上,除了有参构造
@TableName("user")
public class User {
    
    
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

The output results are as follows
insert image description here

[2] value

Take a certain target value from the entity class of the list and put it into the new list result. For example, take the name from the User entity class of the List collection and put it into the List.

The code is as follows (the following two ways of writing are both possible!):

List<String> nameList = list.stream().map(User::getName).collect(Collectors.toList());
List<String> nameList = list.stream().map(it->it.getName()).collect(Collectors.toList());

The effect of execution is as follows:
insert image description here
insert image description here

[3] Grouping: groupingBy

Classify and store the entity classes in the List according to a certain value in the entity class, and use the Map to receive the results. For example, we classify and store the Users in the List into different Lists according to age.

code show as below:

Map<Integer, List<User>> ageMap = list.stream().collect(Collectors.groupingBy(User::getAge));
ageMap.forEach((k,v)->{
    
    
    System.out.println(k+":\n"+String.join("\n",v.toString()));
});

The result of the execution is as follows:
insert image description here

【4】Deduplication

code show as below:

@Test
public void distinctTield() {
    
    
    List<String> numList = Arrays.asList("1","2","2","3","3","4","4","5","6","7","8");
    List<User> userList = userMapper.selectList(null);

    System.out.println(LambdaTest.distinctElements(numList));
    System.out.println(LambdaTest.getNoDuplicateElements(numList));
    System.out.println(LambdaTest.getDuplicateElements(numList));
    System.out.println(LambdaTest.getDuplicateElementsForObject(userList));
    System.out.println(LambdaTest.getNoDuplicateElementsForObject(userList));
    System.out.println(LambdaTest.getElementsAfterDuplicate(userList));
    System.out.println(LambdaTest.getDuplicateObject(userList));
    System.out.println(LambdaTest.getNoDuplicateObject(userList));
    System.out.println(LambdaTest.distinctObject(userList));
}

//(1)把重复的数据删除,只留下一个
//去重后的集合 [1, 2, 3, 4, 5, 6, 7, 8]
public static <T> List<T> distinctElements(List<T> list) {
    
    
    return list.stream().distinct().collect(Collectors.toList());
}

//(2)把所有出现重复的数据都删除
//lambda表达式 去除集合重复的值  [1, 5, 6, 7, 8]
public static <T> List<T> getNoDuplicateElements(List<T> list) {
    
    
    // 获得元素出现频率的 Map,键为元素,值为元素出现的次数
    Map<T, Long> map = list.stream().collect(Collectors.groupingBy(p -> p,Collectors.counting()));
    System.out.println("getDuplicateElements2: "+map);
    return map.entrySet().stream() // Set<Entry>转换为Stream<Entry>
            .filter(entry -> entry.getValue() == 1) // 过滤出元素出现次数等于 1 的 entry
            .map(entry -> entry.getKey()) // 获得 entry 的键(重复元素)对应的 Stream
            .collect(Collectors.toList()); // 转化为 List
}

//(3)把出现重复的数据查出来
//lambda表达式 查找出重复的集合 [2, 3, 4]
public static <T> List<T> getDuplicateElements(List<T> list) {
    
    
    return list.stream().collect(Collectors.collectingAndThen(Collectors
            .groupingBy(p -> p, Collectors.counting()), map->{
    
    
        map.values().removeIf(size -> size ==1); // >1 查找不重复的集合;== 1 查找重复的集合
        List<T> tempList = new ArrayList<>(map.keySet());
        return tempList;
    }));
}

//利用set集合
public static <T> Set<T> getDuplicateElements2(List<T> list) {
    
    
    Set<T> set = new HashSet<>();
    Set<T> exist = new HashSet<>();
    for (T s : list) {
    
    
        if (set.contains(s)) {
    
    
            exist.add(s);
        } else {
    
    
            set.add(s);
        }
    }
    return exist;
}

/**-----------对象List做处理--------------*/

//查找对象中某个原属重复的  属性集合
public static List<String> getDuplicateElementsForObject(List<User> list) {
    
    
    return list.stream().collect(Collectors.groupingBy(p -> p.getName(),Collectors.counting())).entrySet().stream()// 根据name分类,并且统计每个name出现的次数
            .filter(entry -> entry.getValue() > 1) // >1 查找重复的集合;== 查找不重复的集合
            .map(entry -> entry.getKey())
            .collect(Collectors.toList());
}

//查找对象中某个原属未重复的  属性集合
public static List<String> getNoDuplicateElementsForObject(List<User> list){
    
    
    Map<String,List<User>> map = list.stream().collect(Collectors.groupingBy(User::getName));
    return map.entrySet().stream().filter(entry -> entry.getValue().size() == 1)
            .map(entry -> entry.getKey()) // 获得 entry 的键(重复元素)对应的 Stream
            .collect(Collectors.toList()); // 转化为 List

}

//查找对象中某个原属去重后的集合
public static List<String> getElementsAfterDuplicate(List<User> list) {
    
    
    return list.stream().map(o->o.getName()).distinct().collect(Collectors.toList());
}

//对象中某个原属重复的 对象集合
public static List<List<User>> getDuplicateObject(List<User> list) {
    
    
    return list.stream().collect(Collectors.groupingBy(User::getName)).entrySet().stream()
            .filter(entry -> entry.getValue().size() > 1) // >1 查找重复的集合;== 查找不重复的集合
            .map(entry -> entry.getValue())
            .collect(Collectors.toList());
}

//对象中某个原属未重复 对象集合
public static List<User> getNoDuplicateObject(List<User> list) {
    
    
    List<User> cities = new ArrayList<>();
    list.stream().collect(Collectors.groupingBy(User::getName)).entrySet().stream()
            .filter(entry -> entry.getValue().size() ==1) //>1 查找重复的集合;== 查找不重复的集合;
            .map(entry -> entry.getValue())
            .forEach(p -> cities.addAll(p));
    return cities;
}


//根据对象的某个原属去重后的 对象集合
public static List<User> distinctObject(List<User> list) {
    
    
    return list.stream().filter(distinctByKey(User::getName)).collect(Collectors.toList());
}

public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
    
    
    Map<Object, Boolean> seen = new ConcurrentHashMap<>();
    return object -> seen.putIfAbsent(keyExtractor.apply(object), Boolean.TRUE) == null;
}

[5] Sort

code show as below:

@Test
public void sortField() {
    
    
    List<Integer> list = Arrays.asList(10,1,6,4,8,7,9,3,2,5);
    List<User> userList = userMapper.selectList(null);

    System.out.println(sort(list));
    System.out.println(reversed(list));
    System.out.println(sortForObject(userList));
    System.out.println(reversedForObject(userList));
    System.out.println(sortForObject2(userList));
}

//list排序 正序
public static <T> List<T> sort(List<T> list){
    
    
    return list.stream().sorted().collect(Collectors.toList());
}

//list排序 倒序
public static List<Integer> reversed(List<Integer> list){
    
    
    return list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
}

//根据对象某个属性排序  正序
public static List<User> sortForObject(List<User> list){
    
    
    return list.stream().sorted(Comparator.comparing(User::getAge)).collect(Collectors.toList());
}

//根据对象某个属性排序  倒序
public static List<User> reversedForObject(List<User> list){
    
    
    return list.stream().sorted(Comparator.comparing(User::getAge).reversed()).collect(Collectors.toList());
}

//根据对象两个属性排序  正序
public static List<User> sortForObject2(List<User> list){
    
    
    return list.stream().sorted(Comparator.comparing(User::getAge).thenComparing(User::getId)).collect(Collectors.toList());
}

The execution effect is as follows:
insert image description here

[6] The most value, average value and sum of the list

code show as below:

@Test
public void getInfo() {
    
    
    List<Integer> list = Arrays.asList(10,1,6,4,8,7,9,3,2,5);
    List<User> userList = userMapper.selectList(null);
    calculation1(list);
    calculation2(userList);
}

//根据对象某个属性求各自值
///IntSummaryStatistics{count=4, sum=132, min=11, average=33.000000, max=55}
public static IntSummaryStatistics calculation1(List<Integer> list){
    
    
    IntSummaryStatistics stat = list.stream().collect(Collectors.summarizingInt(p -> p));
    System.out.println("max:"+stat.getMax());
    System.out.println("min:"+stat.getMin());
    System.out.println("sum:"+stat.getSum());
    System.out.println("count:"+stat.getCount());
    System.out.println("average:"+stat.getAverage());
    Integer max = list.stream().reduce(Integer::max).get();//得到最大值
    Integer min = list.stream().reduce(Integer::min).get();//得到最小值
    System.out.println("max:"+max+";min:"+min);
    return stat;
}
//根据对象某个属性求各自值
// sum=397,max=29,min=12,ave=23.352941176470587
public static void calculation2(List<User> list){
    
    
    System.out.println("sum="+ list.stream().mapToInt(User::getAge).sum());
    System.out.println("max="+ list.stream().mapToInt(User::getAge).max().getAsInt());
    System.out.println("min="+ list.stream().mapToInt(User::getAge).min().getAsInt());
    System.out.println("ave="+ list.stream().mapToInt(User::getAge).average().getAsDouble());
}

The code operation effect is as follows:
insert image description here

【7】List collection summation

public static void main(String[] args) {
    
    
    List<BigDecimal> list = new ArrayList<>();
    list.add(BigDecimal.valueOf(1.1));
    list.add(BigDecimal.valueOf(1.2));
    list.add(BigDecimal.valueOf(1.3));
    list.add(BigDecimal.valueOf(1.4));

    BigDecimal decimal = list.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
    System.out.println(decimal);
}

【8】Filter

(1) Case 1

//功能描述 过滤
public static List<City> filter(List<City> list){
    
    
    return list.stream().filter(a -> a.getTotal()>44).collect(Collectors.toList());
}

(2) Case 2
For example, there are two Lists, namely notFinishList and finalList, and we want to filter out all the values ​​of notFinishList in the finalList, so we can use filter to achieve

List<Long> taskIds = Array.asList(1,2,3,4);
// 从List<DevelopTask>中取出实体类的id值生成一个List<Long>,假设结果是{1,2}
List<Long> notFinishTaskids = notFinishList.stream().map(DevelopTask::getId).collect(Collectors.toList());
// 从{1,2,3,4}取出除了{1,2}以外的值,也就是{3,4}
taskIds = taskIds.stream().filter(it -> !notFinishTaskids.contains(it)).collect(Collectors.toList());

(3) Case 3
Determine whether a certain value exists in the current collection, and the returned result is a boolean value

Boolean overallReviewRst = details.stream().filter(it->it.getReviewRst().equals(ReviewStatEnum.NO_PASS.getName())).findAny().isPresent();

(4) Case 4
Determine whether a certain value exists in the current collection

audits.stream().anyMatch(a -> po.getIdCard().equals(a.getIdCard()))

(5) Case 5
Judge whether there is a certain value in the current collection, if it exists, filter it out and put it into a new collection

List<TaskXReviewProjRescResponse> details = detailById.stream()
        .filter(d -> String.valueOf(d.getTaskId()).equals(dto.getId()))
        .collect(Collectors.toList());

【9】map traversal

(1) stream traverses key and value

map.forEach((k, v) -> System.out.println("key:value = " + k + ":" + v));

【10】map to list, list to map

(1) Mutual conversion between map and list

//功能描述 List转map
public static void listToMap(List<User> list){
    
    
    //用 (k1,k2)->k1 来设置,如果有重复的key,则保留key1,舍弃key2
    Map<String,User> map = list.stream().collect(Collectors.toMap(User::getName,user -> user, (k1, k2) -> k1));
    map.forEach((k,v) -> System.out.println("k=" + k + ",v=" + v));
}

//功能描述 map转list
public static void mapToList(Map<String,User> map){
    
    
    List<User> list =
            map.entrySet().stream().map(key -> key.getValue()).collect(Collectors.toList());
    System.out.println(list);
    list.forEach(bean -> System.out.println(bean.getName() + "," + bean.getEmail()));
}

(2) map to list

map.entrySet().stream().map(e -> new Person(e.getKey(),e.getValue())).collect(Collectors.toList());
map.keySet().stream().collect(Collectors.toList());
map.values().stream().collect(Collectors.toList());

(3) list to map

Map<Integer, String> result1 = list.stream().collect(
                Collectors.toMap(Hosting::getId, Hosting::getName));

Map<Long, User> maps = userList.stream().collect(Collectors.toMap(User::getId,Function.identity()));

//看来还是使用JDK 1.8方便一些。另外,转换成map的时候,可能出现key一样的情况,如果不指定一个覆盖规则,上面的代码是会报错的。转成map的时候,最好使用下面的方式
Map<Long, User> maps = userList.stream().collect(Collectors.toMap(User::getId, Function.identity(), (key1, key2) -> key2));

[11] Conversion between list and string

//功能描述 字符串转list
public static void stringToList(String str){
    
    
    //不需要处理
    //<String> list = Arrays.asList(str.split(","));
    //需要处理
    List<String> list = Arrays.asList(str.split(",")).stream().map(string -> String.valueOf(string)).collect(Collectors.toList());
    list.forEach(string -> System.out.println(string));
}

//功能描述 姓名以逗号拼接
public static void joinStringValueByList(List<User> list){
    
    
    System.out.println(list.stream().map(User::getName).collect(Collectors.joining(",")));
}

//功能描述 姓名以逗号拼接
public static void joinStringValueByList2(List<String> list){
    
    
    //方式一
    System.out.println(String.join(",", list));
    //方式二
    System.out.println(list.stream().collect(Collectors.joining(",")));
}

【12】Collectors.joining for splicing

(1) Scenario description
If there is a list of users, and you want to display the names of all people, you need to use commas as separators to splice the names

(2) The way of writing before optimization
The idea is to take out all the names and put them into the list, and then use String.join for splicing. Then the code specification verification will prompt that it is not standardized.

String packUser = String.join(",",packPlans.stream().map(it->it.getPackUser()).collect(Collectors.toList()));

(3) The optimized writing method
is directly realized by Collectors.joining

String packUser = list.stream().collect(Collectors.joining(","));

[13] The map method performs conversion operations on the data

The role of the map function is to perform conversion operations on each data element in the pipeline stream

(1) Case 1
Convert each character string in the collection to uppercase

List<String> alpha = Arrays.asList("Monkey", "Lion", "Giraffe", "Lemur");

//不使用Stream管道流
List<String> alphaUpper = new ArrayList<>();
for (String s : alpha) {
    
    
    alphaUpper.add(s.toUpperCase());
}
System.out.println(alphaUpper); //[MONKEY, LION, GIRAFFE, LEMUR]

// 使用Stream管道流
List<String> collect = alpha.stream().map(String::toUpperCase).collect(Collectors.toList());
//上面使用了方法引用,和下面的lambda表达式语法效果是一样的
//List<String> collect = alpha.stream().map(s -> s.toUpperCase()).collect(Collectors.toList());

System.out.println(collect); //[MONKEY, LION, GIRAFFE, LEMUR]

(2) Case 2
Processing non-string type collection elements
The map function can not only process data, but also convert the type of data

List<Integer> lengths = alpha.stream()
        .map(String::length)
        .collect(Collectors.toList());

System.out.println(lengths); //[6, 4, 7, 5]
Stream.of("Monkey", "Lion", "Giraffe", "Lemur")
        .mapToInt(String::length)
        .forEach(System.out::println);

Output: 6 4 7 5

Except mapToInt. There are also usages such as maoToLong, mapToDouble, etc.

(3) Case 3: peek function
Processing object data format conversion
Increase the age of each Employee by one year, replace "M" in gender with "male", and replace F with Female.

public static void main(String[] args){
    
    
    Employee e1 = new Employee(1,23,"M","Rick","Beethovan");
    Employee e2 = new Employee(2,13,"F","Martina","Hengis");
    Employee e3 = new Employee(3,43,"M","Ricky","Martin");
    Employee e4 = new Employee(4,26,"M","Jon","Lowman");
    Employee e5 = new Employee(5,19,"F","Cristine","Maria");
    Employee e6 = new Employee(6,15,"M","David","Feezor");
    Employee e7 = new Employee(7,68,"F","Melissa","Roy");
    Employee e8 = new Employee(8,79,"M","Alex","Gussin");
    Employee e9 = new Employee(9,15,"F","Neetu","Singh");
    Employee e10 = new Employee(10,45,"M","Naveen","Jain");


    List<Employee> employees = Arrays.asList(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);

    /*List<Employee> maped = employees.stream()
            .map(e -> {
                e.setAge(e.getAge() + 1);
                e.setGender(e.getGender().equals("M")?"male":"female");
                return e;
            }).collect(Collectors.toList());*/

    List<Employee> maped = employees.stream()
            .peek(e -> {
    
    
                e.setAge(e.getAge() + 1);
                e.setGender(e.getGender().equals("M")?"male":"female");
            }).collect(Collectors.toList());

    System.out.println(maped);

}

Since the parameter e of map is the return value, the peek function can be used. The peek function is a special map function. When the function has no return value or the parameter is the return value, the peek function can be used.

(4) Case 4: The flatMap function
map can convert the data in the pipeline flow, but what should be done if there are still pipelines in the pipeline? That is to say: how to deal with two-dimensional arrays and two-dimensional collection classes. To achieve a simple requirement:

Print out the set of two strings consisting of "hello" and "world", and each letter of the element. How can we write without Stream? Write 2 layers of for loops, the first layer traverses the string, and splits the string into char arrays, and the second layer of for loops traverses the char array.

List<String> words = Arrays.asList("hello", "word");
words.stream()
        .map(w -> Arrays.stream(w.split("")))    //[[h,e,l,l,o],[w,o,r,l,d]]
        .forEach(System.out::println);

It is impossible to use the map method, and this requirement cannot be realized by the map method. Map can only operate on one-dimensional arrays. There are arrays in arrays, and pipelines in pipelines. It cannot handle every element.

insert image description here

flatMap can be understood as flatly expanding all the data in several sub-pipelines into the parent pipeline for processing.
insert image description here

words.stream()
        .flatMap(w -> Arrays.stream(w.split(""))) // [h,e,l,l,o,w,o,r,l,d]
        .forEach(System.out::println);

【3】Other case studies

[1] Optional.ofNullable: non-null judgment

(1) Function

It is often encountered in work that the query returns null. If there is no null judgment, a null pointer exception will occur if you are not careful. It is also possible to add if judgment processing, but jdk1.8 has a more elegant processing method.

public static void main(String[] args) {
    
    
    List<String> list = null;
    List<String> newList = Optional.ofNullable(list).orElse(Lists.newArrayList());
    newList.forEach(x -> System.out.println(x));
}

If the list collection is not empty, assign the list collection to newList; if the list collection is empty, create an empty object collection and assign it to newList to ensure that the list collection will never be empty, and avoid null pointer exceptions.

(2) Common combinations

(1) optional.ofnullable().orelse()
optional.ofnullable().orelse() is a method of the Optional class in Java 8, used to judge whether the Optional object is empty, and return a default value if it is empty. The ofNullable() method is used to create an Optional object, and the orElse() method is used to return a default value. If the Optional object is not null, returns the Optional object itself. This method can be used to avoid NullPointerException exception.

List<String> lists = null;
List<String> list = new ArrayList<String>();
list.add("你好");
list.add("hello");
List<String> newList = Optional.ofNullable(list).orElse(lists);

(2) optional.ofnullable().ifpresent
is a method of the Optional class in Java 8, and its function is to perform an operation when the Optional object is not empty. Does nothing if the Optional object is empty.

(3) The principle of source code

//静态变量 empty
private static final Optional<?> EMPTY = new Optional<>();
 
//如果对象为空,执行empty()方法;不为空,执行of(value)方法
public static <T> Optional<T> ofNullable(T value) {
    
    
    return value == null ? empty() : of(value);
}

public static<T> Optional<T> empty() {
    
    
    @SuppressWarnings("unchecked")
    Optional<T> t = (Optional<T>) EMPTY;
    return t;
}

public static <T> Optional<T> of(T value) {
    
    
    return new Optional<>(value);
}

1. First execute the ofNullable() method, if the T object is empty, execute the empty() method; if it is not empty, execute the of(value) method; 2.empty
() method, initialize an empty object Optional (empty object and null are not It’s the same thing);
3.of(value) method, use the generic object T for the parameter of the Optional construction method, and return a valued object
4. After the above two steps, it is guaranteed that the Optional is not null, avoiding a null pointer;

(4) Use cases

If the result is not null, perform the following operations, if it is null, do not perform any operations

Optional.ofNullable(result)
                .map(ApiResponse::getData)
                .ifPresent(it -> {
    
    
                    if (StrUtil.isNotBlank(it.getTmpScriptContent())) {
    
    
                        HiveSqlFieldLineageParser parser = HiveSqlFieldLineageParser.build(
                                it.getTmpScriptContent(), false, false);
                        it.setErrors(parser.getErrors());
                    }
                });

Guess you like

Origin blog.csdn.net/weixin_44823875/article/details/130668095