Is there a way to get the index of an object in a list without using a loop

Viewed 293

The trick is that this object MediaContainerModel inherits equals(Object) directly from Object and I can't and don't want to override equals in its class definition. This is what I have at the moment:

private void addMediaContainer(MediaContainerModel newMediaContainer, ProductModel product) {
    List<MediaContainerModel> galleryImages = new ArrayList<>(product.getGalleryImages());
    MediaContainerModel inserted = null;

    // if a MediaContainer with same qualifier as newMediaContainer already exists, replace it 
    // with the new one to prevent duplicates
    for (int i = 0; i < galleryImages.size(); i++) {
        if (galleryImages.get(i).getQualifier().equals(newMediaContainer.getQualifier())) {
            inserted = galleryImages.set(i, newMediaContainer);
        }
    }
    // if not, add it
    if (inserted == null) {
        galleryImages.add(newMediaContainer);
        galleryImages.sort((image1, image2) -> image2.getQualifier().compareTo(image1.getQualifier()));
    }
    product.setGalleryImages(galleryImages);
}

I want to do the same thing without the ugly for-loop by overriding MediaContainerModel.equals(Object) for this method only so I can use List.indexOf(Object) or something with lambdas. Is this possible in Java? If so how? Thanks!

1 Answers

without using a loop

I bet you are looking for the way:

List<MediaContainerModel> galleryImages = new ArrayList<>(product.getGalleryImages());

galleryImages.stream()
    .filter(image -> newMediaContainer.getQualifier()                 // filter the equal ones
                                      .equals(image.getQualifier()))
    .findAny()                                                        // find any existing
    .ifPresent(image -> {                                             // add if present
        galleryImages.add(newMediaContainer);
        galleryImages.sort(Comparator.comparing(MediaContainerModel::getQualifier));
    });

product.setGalleryImages(galleryImages);

Few notes:

  • The filtering uses exhaustive iteration as well as for-loop which means that all elements are iterated and multiple equal MediaContainerModel objects with same qualifiers. That's fine as long as you want to find if there is any qualified (findAny). Otherwise, to find the last one, you have to replace the line with:

    .reduce((first, second) -> second)
    
  • The result using Java Stream API is a bit clumsy. I see you insert a new element and sort the list which means your intention is to keep the list always sorted. If there are no duplicate values allowed, I recommend using rather TreeSet which keeps the elements sorted upon addition or deletion. The whole solution would be the way easier:

    Set<MediaContainerModel> galleryImages = new TreeSet<>(Comparator.comparing(MediaContainerModel::getQualifier));
    galleryImages.addAll(product.getGalleryImages());
    galleryImages.add(newMediaContainer);                      // won't be added if is already present
    product.setGalleryImages(new ArrayList<>(galleryImages));
    

    ... if the ProductModel uses Collection or Set over List, then the last line is more straightforward:

    product.setGalleryImages(galleryImages);
    
Related