Home > Software design >  using stream collection to map or collect images in a multipartFile to save images into an entity pr
using stream collection to map or collect images in a multipartFile to save images into an entity pr

Time:08-22

i have an array of image names that are saved in a MultipartFile[]. these image names image1, image2, image3, image4, image5 are collected from the web and saved as an array of MultipartFile[]

just as an example image1 name could be x1.jpg image2 is abc.jpg image3 is image3.jpg and so on

instead of using a for loop, i would like to use a lambda to save the collection of pics in the MultipartFile[] into a product object.

so Product is has the following variables

public class Product {

private String image1;
private String image2;
...........
...........
private String image5;

}

i need a collection method that looks better than the for loop

something that looks like this


Arrays.stream(multipartFiles).forEach(multipartFile -> {
            String imageName = StringUtils.cleanPath(multipartFile.getOriginalFilename());
            if (count == 0) product.setImage1(imageName);
            if (count == 1) product.setImage2(imageName);
            if (count == 2) product.setImage3(imageName);
            if (count == 3) product.setImage4(imageName);
            if (count == 4) product.setImage5(imageName);
            if (count == 5) product.setImage6(imageName);

            count  ;
        });

my problem is the stream is not allowing me to have count that many times.. the error squiggly line under count is saying

Variable (count) used in lambda expression should be final or effectively final

if someone can improve this great otherwise i would have to use a traditional for - loop

thanks

CodePudding user response:

You can encapsulate logic of "image setting" to your product class like this:

 class Product {

    private final AtomicInteger count = new AtomicInteger();
    private String image1;
    private String image2;
    ...
    private String image5;

    public void setImage(String imageName) {
        switch (count.getAndIncrement()) {
            case  0: image1 = imageName; break;
            case  1: image2 = imageName; break;
            ...
            case  5: image5 = imageName; break;
            default: ...
        }
    }
}

and then in lambda it can be so:

Arrays.stream(multipartFiles).forEach(multipartFile -> {
            String imageName = StringUtils.cleanPath(multipartFile.getOriginalFilename());
            product.setImage(imageName);
        });
    }

but as system desgin it looks very weird.

CodePudding user response:

You should redesign your Product class as:

public class Product {

  private String image;

  public String getImage() { return image; }
  public void setImage(String image) { this.image = image; }

}

and get a list of Products instead of a single Product with multiple fields of the same type:

List<Product> products = Arrays.stream(multipartFiles).map(multipartFile -> {
            String imageName = StringUtils.cleanPath(multipartFile.getOriginalFilename());
            Product product = new Product();            
            product.setImage(imageName);
            return product;
        }).collect(Collectors.toList());

And this should give you a list of products.

Alternatively, you could let your Product class hold a list of image names, and then you will not have to use the Stream API.

  • Related