0

I am trying to improve given algorithm of selecting a Storage box based on Summary info on the box. In order to retrieve the identifer (of summary object) which has the with the highest numItems attribute (of summary object), I would have to sort the Summary[], an array of objects but I just can't figure how to sort by an attribute.

I found numerous examples of creating ArrayList<Int> a = new ArrayList<Int>(); and then Using Collections to get maximum value but here, I am interested in other attribute and I just can't visualize how I would do that. Can you help?

public String selectNextDelivery(StorageBox.Summary[] summaries) throws NoBoxReadyException {
    if (summaries.length != 0) {
        for(StorageBox.Summary summary : summaries){
            if (summary.numItems > 0) {
                return summary.identifier;
            }
        }
    }
    // Otherwise no box is ready
    throw new NoBoxReadyException();
}
5
  • All you need to do is implement a Comparator interface. There already exists many ways to sort a collection of objects Commented Aug 22, 2016 at 5:03
  • Alternatively, you need to not immediately return an element from the list and instead look at all elements, then return the maximum Commented Aug 22, 2016 at 5:05
  • you could use Comparable interface by implementing it in your Summary class Commented Aug 22, 2016 at 5:05
  • @mojtab23 Oh, I accidentally left that part out - I did some search and I did come across implementing Comparable interface but by requirement of school assignment, I can't touch the Summary class. I have to deal with it here. Commented Aug 22, 2016 at 5:10
  • Why do you need to sort the entire array to find the max? Commented Aug 22, 2016 at 7:13

4 Answers 4

3

In Java 8, to get the maximum element in an array of objects using an attribute, use Stream#max() with Comparator.comparingInt()

return Stream.of(summaries)
    .max(Comparator.comparingInt(s -> s.numItems))
    .orElseThrow(() -> new NoBoxReadyException())
    .identifier;

Without Java 8, you can use Collections.max() with a custom Comparator:

try {
    return Collections.max(Arrays.asList(summaries), new Comparator<StorageBox.Summary>() {
        @Override
        public int compare(StorageBox.Summary s1, StorageBox.Summary s2) {
            return Integer.compare(s1.numItems, s2.numItems);
        }
    }).identifier;
} catch (NoSuchElementException nsee) {
    throw new NoBoxReadyException();
}

Or you could implement it yourself with a standard for loop:

if (summaries.length == 0)
    throw new NoBoxReadyException();
StorageBox.Summary max = summaries[0];
for (int i = 1; i < summaries.length; i++)
    if (summaries[i].numItems > max.numItems)
        max = summaries[i];
return max.identifier;
Sign up to request clarification or add additional context in comments.

Comments

1

If you're familiar with Java 8 Streams you can do something like this:

Stream.of(summaries) //creating custom comparator which sorts based on identifier
    .sort(($1, $2) -> Integer.compare($1.identifier, $2.identifier))
    //Do something with your stream

If you want to get the first element from stream sorted by some attribute you can do:

 Stream.of(summaries)
     .max(Comparator.comparingInt(StorageBox.Summary::getIdentifier))
     .orElse(null);

Thanks 4castle for pointing out a Comparator.comparingInt() method

1 Comment

Using sort and findFirst together is overkill. It makes an O(n) operation into O(nlogn)
0

Maybe what you want is using the public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp) api, where it has the comparator with which to determine the maximum element. A null value indicates that the elements' natural ordering should be used.

1 Comment

You didn't mention, but this method is located in the Collections class. It is very useful, though doesn't allow a custom exception.
0

You can use comparators to sort-

Arrays.sort(summaries, new Comparator<Summary>() {

    @Override
    public int compare(Summary o1, Summary o2) {

        return o1.numItems.compareTo(o2.numItems);
    }           
});

or Use the Collections api alongwith the Comparator to retrieve the max

Summary maxSummary = Collections.max(Arrays.asList(summaries), 
                                   new Comparator<Summary>() {

            @Override
            public int compare(Summary o1, Summary o2) {

                return o1.numItems.compareTo(o2.numItems);
            }           
        });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.