Calihog Calihog - 28 days ago 12
Java Question

How do you sort a vector of custom objects by attribute, that is a Map of other custom objects?

The hierarchy goes like:


  1. Class Drug - it has drugs name and price.

  2. Class Supplier - it holds a Map of
    <Drug drug, int quantity>
    .



Now I have a
Vector<Suppliers>
(which holds, let's say 5 suppliers) and I want to sort in descending order of the quantity of an user inputted drugs name.

Is this even possible? I've tried using comparators but I can't get it working.

Ok, what I tried to do is put only the suppliers, that have the passed as parameter drug in a new
List
and THEN perform the sort on the list. I think this is a good workaround, but then I need to change the 'sort' somehow.

Here is the method where I iterate over all suppliers and check if they have the drug, if they do -> add them in the new list and try to sort it in the end.

public List<Supplier> getSortedSuppliersByQuantity(Drug drug) {
List <Supplier> sortedSuppliers = new ArrayList <Supplier>();
for(Supplier s : suppliers) {
for(Entry<Drug, Integer> entry : s.getListOfDrugs().entrySet()) {
if(entry.getKey().getDrugsName().equals(drug.getDrugsName()));
sortedSuppliers.add(s);
}
}
sort(drug, sortedSuppliers);
return sortedSuppliers;
}


Problem is that I get the
NullPointerException
at the
sort
line.

I think that the
sort
method, that you suggested, needs to be changed to somehow act on the new List and not the old one?

Stacktrace for @Andrew

Exception in thread "main" java.lang.NullPointerException
at java.util.Objects.requireNonNull(Unknown Source)
at java.util.Optional.<init>(Unknown Source)
at java.util.Optional.of(Unknown Source)
at myapp.Supplier.getKeyExtractor(Supplier.java:22)
at myapp.Orders.lambda$0(Orders.java:89)
at java.util.Comparator.lambda$comparing$77a9974f$1(Unknown Source)
at java.util.TimSort.countRunAndMakeAscending(Unknown Source)
at java.util.TimSort.sort(Unknown Source)
at java.util.Arrays.sort(Unknown Source)
at java.util.ArrayList.sort(Unknown Source)
at java.util.Collections.sort(Unknown Source)
at myapp.Orders.sort(Orders.java:89)
at myapp.Orders.getSortedSuppliersByQuantity(Orders.java:106)
at myapp.main.main(main.java:22)

Answer

The following comparator performs the same actions like yours does, but in a shorter Java 8 form:

public void sort(Drug drug, Vector<Supplier> suppliers) {
    Collections.sort(suppliers, Comparator.comparing(s -> s.getDrugs().get(drug)));
}

The problem is possible when either a map doesn't contain the given drag or a supplier doesn't have drugs to trade (NullPointerException).

How to solve? Add null checks or pass valid arguments to the method.


EDIT:

I wrote the getKeyExtractor method which will throw an exception with a detailed message (if something bad happens) to know what is going on:

public void sort(Drug drug, Vector<Supplier> suppliers) {
    Collections.sort(suppliers, Comparator.comparing(s -> Supplier.getKeyExtractor(s, drug)));
}

public static Integer getKeyExtractor(Supplier supplier, Drug drug) {
    return Optional.ofNullable(Optional.ofNullable(supplier.getDrugs())
                               .orElseThrow(() -> new IllegalArgumentException("drugs is null")).get(drug))
                   .orElseThrow(() -> new IllegalArgumentException("the drug couldn't be found"));
}

P.S.

I would suggest you to use a List in a pair with the ArrayList here instead of a Vector.

Comments