Bartek
Bartek

Reputation: 2219

Modify list - stream approach

I want to modify list of already created objects in stream. I realized three approaches that may do that, but I not sure about their performance and possible downsize.

  1. Return same object - not waste of time to creating new object, but object is mutable
  2. Create new object - parameter is not modified, but for huge object creation is time consuming
  3. Modify parameter - can only use ForEach, no parallel usage

Code below code with explaining comments.

public class Test {

    public static void main(String[] args) {
        //Already created objects
        List<Foo> foos0 = Arrays.asList(new Foo("A"));

        //However I need to apply some modification on them, that is dependent on themselves

        //1. Returning same object
        List<Foo> foos1 = foos0.stream().map(Test::modifyValueByReturningSameObject).collect(Collectors.toList());

        //2. Creating new object
        List<Foo> foos2 = foos0.stream().map(Test::modifyValueByCreatingNewObject).collect(Collectors.toList());

        //3. Modifying param
        foos0.stream().forEach(Test::modifyValueByModifyingParam);
    }

    //Lets imagine that all methods below are somehow dependent on param Foo
    static Foo modifyValueByReturningSameObject(Foo foo) {
        foo.setValue("fieldValueDependentOnParamFoo");
        return foo;
    }

    static Foo modifyValueByCreatingNewObject(Foo foo) {
        Foo newFoo = new Foo("fieldValueDependentOnParamFoo");
        return newFoo;
    }

    static void modifyValueByModifyingParam(Foo foo) {
        foo.setValue("fieldValueDependentOnParamFoo");
        return;
    }
}

public class Foo {

    public String value;

    public Foo(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

So the question is which is the most stream approach?

EDIT: By stream approach I mean, that the most advantages in sense of performence.

EDIT2: 1. Which is functional approach? 2. Which is best in sense of performance?

Upvotes: 1

Views: 98

Answers (2)

kai
kai

Reputation: 905

The different aproaches will in your case most likely result in no difference regarding performance.

Reason: optimization. Java will not really create new classes and will use direct access to fields. It might(and will if analysis sugests it) even skip a whole chain of calls and replace it by a precalculated value. Java runtime even utilizes a profiler to optimize and find hotspots...

Also: Regarding performance it is in general(particular cases may differ) more important to create a simple structure and help the runtime to make the right assumptions. So if you hide what you are doing in unesseary manual "optimization", that hides optimization posibilities(lots of branches/decisions, unnecessary pinning, chain of "unknown" methods ...) from the runtime you might end up with a slower result.

For clarity and sideffects(see also other answer) I rather use the version that creates new instances.

Upvotes: 1

Arnaud Denoyelle
Arnaud Denoyelle

Reputation: 31245

The javadoc states that Streams should avoid side effects :

Side-effects in behavioral parameters to stream operations are, in general, discouraged, as they can often lead to unwitting violations of the statelessness requirement, as well as other thread-safety hazards.

So, you should prefer the solution where you create new objects instead of modifying existing ones.

Upvotes: 2

Related Questions