API потока Java 8, как собрать список в объект

У меня есть два простых класса ImageEntity и ImageList

как собрать список результатов ImageEntity в ImageList?

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

учебный класс

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

а также

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);
 }

}

Это не элегантное решение

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));

Может быть решение через сбор AndThen ?

какие еще есть идеи?


person Atum    schedule 26.04.2016    source источник


Ответы (3)


Поскольку ImageList может быть создан из List<ImageEntity>, вы можете использовать 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));

Отдельно стоит отметить, что вам не нужно использовать фигурные скобки в лямбда-выражении. Вы можете использовать file -> new ImageEntity(file.getName(), file.lastModified(), rootWebPath + "/" + file.getName())

person Misha    schedule 26.04.2016
comment
Хороший ! очень элегантно! Большое спасибо! - person Atum; 26.04.2016

вы также можете попробовать ниже

ImageList imgList = new ImageList (files.stream().
  .map(file -> { return new ImageEntity(file.getName(), file.lastModified(), rootWebPath + "/" + file.getName()) })
  .collect(Collectors.toList()));
person Shirishkumar Bari    schedule 26.04.2016
comment
Это действительно странно, как Collectors.toList() возвращает Object вместо списка объектов. Объясните пожалуйста ? - person hzitoun; 05.01.2018
comment
Это ошибка с моей стороны, я принял ImageList за List<Images>. У нас должно получиться что-то вроде .collect(converttoImageList()); - person Shirishkumar Bari; 08.01.2018

Недостаток подхода collectAndThen заключается в создании списка и его последующем копировании.

Если вам нужно что-то более повторно используемое, чем ваш первоначальный пример collect, и что, как и ваш пример, не заканчивается созданием дополнительной копии в сборщике collectingAndThen, вы можете взять три параметра collect и создать функцию, аналогичную Collectors.toList(). который собирается прямо в ваш ImageList, например:

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

Затем вы можете использовать его следующим образом:

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