About [Java] [StreamAPI] allMatch ()

Stream pitfalls

It should be noted that Java 8 Stream is very convenient, but it only provides a "flow". Among them, ʻall Match` is very dangerous! On the contrary, side effects occur if not used with caution. This is because allMatch performs short-circuit evaluation (if there is something that does not meet the judgment conditions, the subsequent processing is not continued and the processing ends there).

Test content

Create a class that holds a character string, determine whether the string length is all 5 characters or less for the List that holds it, and if data of 6 characters or more is included, that character A program that substitutes the string sorry instead of a column. Tested with the following four processing methods.

--A. Execute allMatch directly on List --B. Map and then execute allMatch in Stream processing --C: Map and save to List once, then open a new Stream and execute allMatch --D: Filter the processing result and compare the number with the list length of the target that is streaming Stream

Sample code. I think it's easy.

MyProject.java


public class MyProject {

    public static void main(String[] args) {

        List<String> baseStrList = Arrays.asList("test", "tetetete", "tetetete", "tetetete", "tetetete");
        List<TestData> listA = baseStrList.stream().map(TestData::new).collect(Collectors.toList());
        List<TestData> listB = baseStrList.stream().map(TestData::new).collect(Collectors.toList());
        List<TestData> listC = baseStrList.stream().map(TestData::new).collect(Collectors.toList());
        List<TestData> listD = baseStrList.stream().map(TestData::new).collect(Collectors.toList());

        boolean a = listA.stream().allMatch(TestData::checkLength);
        boolean b = listB.stream().map(TestData::checkLength).allMatch(e -> e);
        List<Boolean> list3Temp = listC.stream().map(TestData::checkLength).collect(Collectors.toList());
        boolean c = list3Temp.stream().allMatch(e -> e);
        boolean d = listD.size() == listD.stream().filter(TestData::checkLength).count();

        System.out.println("a:" + a + ", list:" + listA.toString());
        System.out.println("b:" + b + ", list:" + listB.toString());
        System.out.println("c:" + c + ", list:" + listC.toString());
        System.out.println("d:" + d + ", list:" + listD.toString());
    }


    public static class TestData {
        public String content = "fefe";

        @Override
        public String toString() {
            return content;
        }

        public TestData(String a) {
            this.content = a;
        }

        public boolean checkLength() {

            if (getContent().length() > 5) {
                setContent("sorry");
                return false;
            }
            return true;
        }

        public String getContent() {
            return content;
        }

        public void setContent(String content) {
            this.content = content;
        }
    }
}

result

a:false, list:[test, sorry, tetetete, tetetete, tetetete]
b:false, list:[test, sorry, tetetete, tetetete, tetetete]
c:false, list:[test, sorry, sorry, sorry, sorry]
d:false, list:[test, sorry, sorry, sorry, sorry]

Result consideration

--A: Due to the short-circuit evaluation of allMatch, sorry is assigned only to the second element, and the elements after that are left unprocessed. --B: Even if you put map () of Stream API, it is in the hands of allMatch (), so unfortunately the result is the same as A. --C: Since a new List is created once, it is inefficient, but all elements are processed correctly. --D: This should be more efficient than c because it doesn't generate a new List. .. ..

From the above, we can see that we need to understand how to use allMatch correctly.

Personally, when using allMatch, I think that it is only when you want to check something against List. If the data is destroyed like this time, or if you perform some special processing and aggregate the results, it seems better to use the C or D method.

[2017/10/23 09:40 postscript] Also, of course, allMatch for empty list is true, so be careful. The same result can be obtained with the D method.

By the way

If you use lombok, it will be easier, so let's use it.

MyProject.java



import lombok.Data;
import lombok.val;

import java.util.Arrays;
import java.util.stream.Collectors;

public class MyProject {

    public static void main(String[] args) {

        val baseStrList = Arrays.asList("test", "tetetete", "tetetete", "tetetete", "tetetete");
        val listA = baseStrList.stream().map(TestData::new).collect(Collectors.toList());
        val listB = baseStrList.stream().map(TestData::new).collect(Collectors.toList());
        val listC = baseStrList.stream().map(TestData::new).collect(Collectors.toList());
        val listD = baseStrList.stream().map(TestData::new).collect(Collectors.toList());

        val a = listA.stream().allMatch(TestData::checkLength);
        val b = listB.stream().map(TestData::checkLength).allMatch(e -> e);
        val list3Temp = listC.stream().map(TestData::checkLength).collect(Collectors.toList());
        val c = list3Temp.stream().allMatch(e -> e);


        val d = listD.size() == listD.stream().filter(TestData::checkLength).count();

        System.out.println("a:" + a + ", list:" + listA.toString());
        System.out.println("b:" + b + ", list:" + listB.toString());
        System.out.println("c:" + c + ", list:" + listC.toString());
        System.out.println("d:" + d + ", list:" + listD.toString());
    }
    
    @Data
    public static class TestData {
        public String content = "fefe";

        @Override
        public String toString() {
            return content;
        }

        public TestData(String a) {
            this.content = a;
        }

        public boolean checkLength() {

            if (getContent().length() > 5) {
                setContent("sorry");
                return false;
            }
            return true;
        }
    }
}

Recommended Posts

About [Java] [StreamAPI] allMatch ()
About Java interface
[Java] About Java 12 features
[Java] About arrays
Something about java
Where about java
About Java features
About Java threads
[Java] About interface
About Java class
About Java arrays
About java inheritance
About interface, java interface
About List [Java]
About java var
About Java literals
About Java commands
About Java log output
About Java functional interface
Java, about 2D arrays
About class division (Java)
About Java StringBuilder class
[Java] About Singleton Class
About Java method binding
[Java] About anonymous classes
About method splitting (Java)
[Java Silver] About initialization
About Java Array List
About Java Polymorphism super ()
About inheritance (Java Silver)
About Java String class
About Java access modifiers
About Java lambda expressions
About Java entry points
About Java 10 Docker support
Personal summary about Java
[Java] About enum type
All about Java programming
About java abstract class
A note about Java GC
About an instance of java
What I researched about Java 6
[Gradle] About Java plug-in tasks
About Java variable declaration statements
What I researched about Java 9
[Java] About try-catch exception handling
About Java class loader types
[Java Silver] About equals method
[Java] About String and StringBuilder
What I researched about Java 7
About Alibaba Java Coding Guidelines
About Java class variables class methods
About Java Packages and imports
About abstract classes in java
[Android / Java] Learned about DataBinding
What I researched about Java 5
About Java static and non-static methods
How about TECH ACADEMY ?? [Java course]
[Introduction to Java] About lambda expressions
About fastqc of Biocontainers and Java
About Lambda, Stream, LocalDate of Java8