简体   繁体   中英

Sorting a list of <Object a> by the value of it's Map <Object b, Integer int> results in a crash for objects with different private fields

I have the following list of objects of type Supplier . Every object has a private Map <Drug, Integer> (every Drug has price and name) and I am sorting them successfuly by the Maps value. However, I get a crash when I try to sort the list, if there is Drugs with different price. I'm pretty sure that this is something really small that I am missing here, but I've hit the wall here. Here is my Supplier class:

public class Supplier  {
    private String supplierName = "";
    private String representative = "";
    private String representativesPhoneNumber = "";

    private Map<Drug, Integer> listOfDrugs = new HashMap<Drug, Integer>();

    Supplier(String n, String rep, String repPhoneNum, String drugName, double drugPrice, int stock) {
        this.supplierName = n;
        this.representative = rep;
        this.representativesPhoneNumber = repPhoneNum;
        listOfDrugs.put(new Drug(drugName, drugPrice), stock);
    }

    public Map<Drug, Integer> getListOfDrugs() {
        return this.listOfDrugs;
    }

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

public int getDrugsStock(String drugsName) {
    for (Entry<Drug, Integer> entry : listOfDrugs.entrySet())
    {
        if(entry.getKey().getDrugsName().equalsIgnoreCase(drugsName)) {
            return listOfDrugs.get(entry.getKey());
        }
    }
    return 0;
}

}

It has a Map if objects <Drug, Integer> . Here is my Drug class:

public class Drug {
    private String name = "";
    private double price = 0.0;

    Drug(String n, double p) {
        this.name = n;
        this.price = p;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        long temp;
        temp = Double.doubleToLongBits(price);
        result = prime * result + (int) (temp ^ (temp >>> 32));
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Drug other = (Drug) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (Double.doubleToLongBits(price) != Double.doubleToLongBits(other.price))
            return false;
        return true;
    }
}

Most of the code is trimmed, for the sake of spam. :)

And my Orders class, where I actually do the sorting:

public class Orders {
    private Map <Drug, Integer> orderedDrugs = new HashMap <Drug, Integer>();
    private Vector<Supplier> suppliers = new Vector <Supplier>();   

        public List<Supplier> sort(Drug drug, List<Supplier> suppliers) {
    List<Supplier> bufferList = new ArrayList <Supplier>();
    for (Supplier s : suppliers) {
        if(s.getDrugsStock(drug.getDrugsName()) != 0) {
            bufferList.add(s);
        }
    }
    Collections.sort(bufferList, Comparator.comparing(s -> Supplier.getKeyExtractor(s, drug)));
    Collections.reverse(bufferList);
    return bufferList;
}
}

The code is trimmed again, only displaying the needed methods for the actual problem.

And here is a sample from my main :

            Drug drug = new Drug("product1", 27.6);
            for(Supplier s : orders.sort(drug, orders.getSupplierList())) {
                System.out.println(s);
            }

So here, if I have 2 Suppliers and they both have Drugs with name product1 , but with different prices, I get the following crash:

xception in thread "main" java.lang.IllegalArgumentException: the drug couldn't be found
    at myapp.Supplier.lambda$1(Supplier.java:72)
    at java.util.Optional.orElseThrow(Unknown Source)
    at myapp.Supplier.getKeyExtractor(Supplier.java:72)
    at myapp.Orders.lambda$0(Orders.java:97)
    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:97)
    at myapp.main.main(main.java:77)

I want to sort the list of <Suppliers> by the Suppliers Map value, for different Drugs prices. Example: Supplier1 <new Drug(drug1, 7.66), 50> Supplier2 <new Drug(drug1, 6.72), 30> Supplier3 <new Drug(drug1, 8.94), 15> The Map's value is the quantity of the Drug and I want to sort all suppliers by it. Thank you for the help in advance and I'm sorry for the long post!

During filling the bufferList in Orders.sort() you only check for the Drug.name and not for the price. In this case you get a supplier in the list to sort which not holds the Drug.

You have more than one Drug with the same name.

Suppose supplier1 sells a Drug called "Tylenol" and supplier2 also sells a Drug called "Tylenol" but these are separate Drugs.

You then create a third Drug called "Tylenol", but when you call supplier1.getDrugsStock("Tylenol") it returns the first Drug and when you call supplier2.getDrugsStock("Tylenol") it returns the second Drug, so you add both of these suppliers to bufferList .

Then you call supplier1.getDrugsStock().get(thirdDrug) which returns null because supplier1 only stocks the first Drug.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM