Atum
Atum

Reputation: 1301

Java 8 stream api how to collect List to Object

I have two simple class ImageEntity and ImageList

how to collect result list ImageEntity to ImageList ?

List<File> files = listFiles();
        ImageList imageList = files.stream().map(file -> {
            return new ImageEntity(
                                   file.getName(), 
                                   file.lastModified(), 
                                   rootWebPath + "/" + file.getName());
        }).collect(toCollection(???));

class

public class ImageEntity {
private String name;
private Long lastModified;
private String url;
 ...
}

and

public class ImageList {
 private List<ImageEntity> list;

 public ImageList() {
    list = new ArrayList<>();
 }

 public ImageList(List<ImageEntity> list) {
    this.list = list;
 }
 public boolean add(ImageEntity entity) {
    return list.add(entity);
 }
 public void addAll(List<ImageEntity> list) {
     list.addAll(entity);
 }

}

It's not an elegant solution

ImageList imgList = files.stream().
  .map(file -> { return new ImageEntity(file.getName(), file.lastModified(), rootWebPath + "/" + file.getName()) })
  .collect(ImageList::new, (c, e) -> c.add(e), (c1, c2) -> c1.addAll(c2));

It can be a solution through collectingAndThen ?

what else have any ideas?

Upvotes: 10

Views: 36283

Answers (3)

Hank D
Hank D

Reputation: 6471

The collectingAndThen approach has the downside of creating a list and then copying it.

If you'd like something more reusable than your initial collect example, and that, like your example, doesn't end doing an extra copy in the collectingAndThen collector, you can take the three parameters of the collect and make a function similar to Collectors.toList() that collects straight to your ImageList, like this:

public static Collector<ImageEntity,?,ImageList> toImageList() {
    return Collector.of(ImageList::new, (c, e) -> c.add(e), (c1, c2) -> c1.addAll(c2));
}

You could then use it like this:

ImageList imgList = files.stream().
    .map(file -> new ImageEntity(file.getName(), file.lastModified(), rootWebPath + "/" + file.getName()))
    .collect(toImageList());

Upvotes: 1

Shirish Bari
Shirish Bari

Reputation: 2722

you can try below also

ImageList imgList = new ImageList (files.stream().
  .map(file -> { return new ImageEntity(file.getName(), file.lastModified(), rootWebPath + "/" + file.getName()) })
  .collect(Collectors.toList()));

Upvotes: 1

Misha
Misha

Reputation: 28133

Since ImageList can be constructed from a List<ImageEntity>, you can use Collectors.collectingAndThen:

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.collectingAndThen;

ImageList imgList = files.stream()
    .map(...)
    .collect(collectingAndThen(toList(), ImageList::new));

On a separate note, you don't have to use the curly braces in your lambda expression. You can use file -> new ImageEntity(file.getName(), file.lastModified(), rootWebPath + "/" + file.getName())

Upvotes: 18

Related Questions