rasilvap
rasilvap

Reputation: 2149

How to remove the last element from a Stream Collection (DockerClient)

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!

Upvotes: 0

Views: 731

Answers (2)

Holger
Holger

Reputation: 298203

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.

Upvotes: 2

Nowhere Man
Nowhere Man

Reputation: 19545

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

Upvotes: 0

Related Questions