Java 8流API如何将List收集到对象中

9

我有两个简单的类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));

通过使用collectingAndThen,它可以成为一个解决方案?

还有其他的想法吗?

3个回答

17

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

另外需要说明的是,在lambda表达式中您不必使用大括号。您可以使用 file -> new ImageEntity(file.getName(), file.lastModified(), rootWebPath + "/" + file.getName())


好的!非常优雅!非常感谢你! - Atum

1
你可以尝试下面的内容。
ImageList imgList = new ImageList (files.stream().
  .map(file -> { return new ImageEntity(file.getName(), file.lastModified(), rootWebPath + "/" + file.getName()) })
  .collect(Collectors.toList()));

1
这真的很奇怪,Collectors.toList() 返回 Object 而不是对象列表。你能解释一下吗? - hzitoun
这是我的错误,我把ImageList当作了List<Images>。我们应该有类似.collect(converttoImageList());的东西。 - Shirishkumar Bari

1

采用collectingAndThen方法的缺点是会创建一个列表,然后再复制它。

如果您想要比起最初的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());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接