Как удалить последний элемент из коллекции потоков (DockerClient)

#java #collections #java-stream #spotify-docker-client

Вопрос:

Привет, у меня есть коллекция потоков, и я отсортировал ее по дате создания, мне нужно удалить все элементы из этой коллекции, но меньше окончательного:

Это мой код:

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

В этом списке мои элементы отсортированы по дате создания, и мне нужно удалить все элементы, за исключением последнего.

я попробовал что-то вроде:

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

Но мне хотелось чего-нибудь более изысканного, спасибо!

Комментарии:

1. Не можете ли вы создать новый список, в котором есть только последний элемент, как в List.of(response.get(response.size() - 1) или аналогичный?

2. Мне нужно использовать dockerClient.removeImage(image.id()); чтобы удалить все изображения докера за вычетом последнего

Ответ №1:

Эта задача может быть решена просто и эффективно с помощью традиционного цикла:

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

Этот цикл повторяет изображения и удаляет изображение, как только был найден более свежий соответствующий объект, без необходимости дополнительного хранения или сортировки. Когда цикл завершится, все, кроме самого последнего совпадающего изображения, будут удалены, и в качестве бонуса в переменной будет сохранен самый последний объект mostRecent .

Комментарии:

1. Если, как было предложено в вашем другом вопросе, created() на самом деле возвращает строку, содержащую число, замените строку if(toRemove.created().compareTo(mostRecent.created()) > 0) … на if(Integer.parseInt(toRemove.created()) < Integer.parseInt(mostRecent.created())) …

Ответ №2:

Похоже, что необходимо извлечь изображение с последней created датой, поэтому Collectors::maxBy его можно использовать вместо сортировки списка и удаления ненужных элементов:

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

Если это действительно необходимо, чтобы получить List результат:

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

Обновить

Как только будет найдено последнее изображение, при необходимости его можно использовать forEach для удаления изображений из контейнера Docker:

 List<Image> images = dockerClient.listImages()
    .stream()
    .filter(image -> image.labels() != null amp;amp; 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()))
    );
 

Комментарии:

1. Мне нужно удалить из docker все изображения, за исключением самого последнего, по этой причине мне нужны все старые изображения, просто чтобы использовать dockerClient.removeImage(image.id()) и удалите изображение по его идентификатору

2. @rasilvap вы можете проверить обновление