0

Hi I have a stream Collection and I sorted it by the date creation, I need to remove all the elements from this Collections, but less the final one:

This is my code:

List<com.spotify.docker.client.messages.Image> response = dockerClient.listImages()
          .stream()
          .filter(image -> image.labels() != null && image.labels().containsKey("wantedLabel"))
          .sorted((o1, o2) -> o2.created().compareTo(o1.created()))
          .collect(
              Collectors.toList());

In this list I have my elements sorted by created date and I need to remove all the elements less the final one.

i tried something like:

 if (response.stream().iterator().hasNext()) {
        response.remove(count);
        count++;
 }

But I wanted to have something more sophisticated, thanks!

Nowhere Man
  • 19,170
  • 9
  • 17
  • 42
rasilvap
  • 1,771
  • 3
  • 31
  • 70

2 Answers2

2

This task can be solved simple and efficient with a traditional loop:

com.spotify.docker.client.messages.Image mostRecent = null;
for(var image: dockerClient.listImages()) {
    if(image.labels() == null || !image.labels().containsKey("wantedLabel")) continue;
    if(mostRecent == null) mostRecent = image;
    else {
        var toRemove = image;
        if(toRemove.created().compareTo(mostRecent.created()) > 0) {
            toRemove = mostRecent;
            mostRecent = image;
        }
        dockerClient.removeImage(toRemove.id());
    }
}

This loop iterates over the images and removes an image as soon as a more recent matching object has been found, without the need for additional storage nor sorting. When the loop completes, all but the most recent matching image have been removed and, as a bonus, the retained most recent object is held in the variable mostRecent.

Holger
  • 285,553
  • 42
  • 434
  • 765
  • 1
    If, like suggested in your other question, `created()` actually returns a string containing a number, replace the line `if(toRemove.created().compareTo(mostRecent.created()) > 0) …` with `if(Integer.parseInt(toRemove.created()) < Integer.parseInt(mostRecent.created())) …` – Holger Sep 29 '21 at 18:29
0

It seems that an image with the latest created date needs to be retrieved, therefore Collectors::maxBy could be used instead of sorting the list and removing unneeded elements:

Image latestImage = dockerClient.listImages()
          .stream()
          .filter(image -> image.labels() != null && image.labels().containsKey("wantedLabel"))
          .collect(Collectors.maxBy(Image::created)) // Optional<Image>
          .orElse(null);

If it is really needed to have a List as result:

List<Image> response = dockerClient.listImages()
          .stream()
          .filter(image -> image.labels() != null && image.labels().containsKey("wantedLabel"))
          .collect(Collectors.maxBy(Image::created)) // Optional<Image>
          .map(Collections::singletonList)
          .orElseGet(() -> Collections.emptyList());

Update

As soon as the latest image is found, it is possible to use forEach to delete the images from the Docker container if necessary:

List<Image> images = dockerClient.listImages()
    .stream()
    .filter(image -> image.labels() != null && image.labels().containsKey("wantedLabel"))
    .collect(Collectors.toList());

images.stream()
    .collect(Collectors.maxBy(Image::created)) // Optional<Image>
    .ifPresent(latest -> 
        images.stream()
              .filter(img -> !latest.getId().equals(img.getId()))
              .forEach(img -> dockerClient.removeImage(img.getId()))
    );
Nowhere Man
  • 19,170
  • 9
  • 17
  • 42
  • I need to delete from docker all the images less the most recent one, for that reason I need all the older images, just to use the dockerClient.removeImage(image.id()) and remove the image by its Id – rasilvap Sep 28 '21 at 19:19
  • @rasilvap youmay check the update – Nowhere Man Sep 28 '21 at 19:41