Java – Can streams create new objects?

Can streams create new objects?… here is a solution to the problem.

Can streams create new objects?

I

will try to simplify the situation I am facing. There are 2 entities:

class Foo {
    String fooProperty;

@OneToOne
    Bar bar;
}

class Bar {
    String barProperty;
}

There is also a DTO class with attributes for Foo and Bar:

class FooDto {
    String fooProperty;
    String barProperty;

public static FooDto from(Foo foo) {
        return new FooDto(foo.fooProperty, foo.bar.barProperty);
    }
}

FooDto is used to transfer large amounts of data and can be easily transformed using streams:

fooList.stream().map(FooDto::from).( ...)

Now, the requirements have changed and a Foo can have multiple Bars:

@OneToMany
List<Bar> bar;

It is also required to generate a FooDto for each included Bar, like this:

Foo(fooProperty="foo1", bar=[Bar(barProperty="bar1"), Bar(barProperty="bar2")])

will be converted to:

[FooDto(fooProperty="foo1", barProperty="bar1"), FooDto(fooProperty="foo1", barProperty="bar2")]

I

managed to solve it with the middle list, but I’m still not sure if it’s the best solution.

I was wondering if it was possible to do something similar using pure streaming. I can use map and filter and generate size equal to/less than
Original input, but I don’t know how to generate a result with more elements.

Solution

The action you’re looking for is called flatMap.

It operates on the stream of Foo

objects, taking as a parameter a function that converts the Foo object to a FooDto object stream and returns the stream composition stream of the FooDto object:

class FooDto {
    String fooProperty;
    String barProperty;

public FooDto(String fooProperty, String barProperty) {
        this.fooProperty = fooProperty;
        this.barProperty = barProperty;
    }

public static Stream<FooDto> from(Foo foo) {
        return foo.bars.stream().map(bar -> new FooDto(foo.fooProperty, bar.barProperty));
    }
}

And then:

List<FooDto> result = fooList.stream().flatMap(FooDto::from).( Collectors.toList());

Related Problems and Solutions