Reputation: 11
I am new to using lambdas in Java 8 and I am having trouble with sorting.
Basically, I have 4 fields in a class, then in my main method I create an array of objects to sort. I want to be able to use Stream#sorted() to sort my output by the product of 2 fields (price
* quantity
).
This is the class I want to sort:
public class Invoice {
private final int partNumber;
private final String partDescription;
private int quantity;
private double price;
// constructor
public Invoice(int partNumber, String partDescription, int quantity, double price) {
if (quantity < 0) // validate quantity
throw new IllegalArgumentException("Quantity must be >= 0");
if (price < 0.0) // validate price
throw new IllegalArgumentException("Price per item must be >= 0");
this.partNumber = partNumber;
this.partDescription = partDescription;
this.quantity = quantity;
this.price = price;
} // end constructor
//get and set accessors
}
Here is my test class with my array of objects:
public class ProcessInvoices {
public static void main(String[] args) {
//declare array of invoice objects
Invoice[] invoices = {
new Invoice(83, "Electric sander", 7, 57.98),
new Invoice(24, "Power saw", 18, 99.99),
new Invoice(7, "Sledge hammer", 11, 21.50),
new Invoice(77, "Hammer", 76, 11.99),
new Invoice(39, "Lawn mower", 3, 79.50),
new Invoice(68, "Screw driver", 106, 6.99),
new Invoice(56, "Jig saw", 21, 11.00),
new Invoice(3, "Wrench", 34, 7.50)};
System.out.println("\nInvoices mapped to description and invoice amount");
Arrays.stream(invoices)
.sorted(Comparator.comparing(invoice.getQuantity() * invoice.getPrice()))
.map(invoice -> String.format("Description: %-15s Invoice amount: $%,6.2f", invoice.getPartDescription(), (invoice.getQuantity() * invoice.getPrice())))
.forEach(invoice -> System.out.printf("%s%n", invoice));
}
In the stream I map the partDescription
to the product of quantity
and price
which gives the total price for an invoice. This is what I want to sort by, the total price of the invoice, but I do not know the correct way of doing this with the sorted()
method.
I try to simply compare by quantity * price
but that tells me that the variable "invoice is not recognized". If I try to sort after the map()
statement, that does not work either. I have also tried using a different variable, amount
, no luck there either.
How do I sort by the product of two fields by using sorted()
?
Upvotes: 0
Views: 1827
Reputation: 11978
I would strongly recommend you to create a method on Invoice
which does the calculation:
public double getTotalPrice() {
return quantity * price;
}
This is essantially just the basic object oriented way to do it.
You could then use this as a method reference and avoid having the logic used for sorting inside the lambda:
.sorted(Comparator.comparingDouble(Invoice::getTotalPrice))
Note that you could use the built-in comparator for sorting doubles.
As a side note, you might want to use BigDecimal
if you want to have an exact floating point precision.
Upvotes: 0
Reputation: 4055
This will also do it:
public class InvoiceTest {
@Test
public void testName() throws Exception {
//declare array of invoice objects
Invoice[] invoices = {
new Invoice(83, "Electric sander", 7, 57.98),
new Invoice(24, "Power saw", 18, 99.99),
new Invoice(7, "Sledge hammer", 11, 21.50),
new Invoice(77, "Hammer", 76, 11.99),
new Invoice(39, "Lawn mower", 3, 79.50),
new Invoice(68, "Screw driver", 106, 6.99),
new Invoice(56, "Jig saw", 21, 11.00),
new Invoice(3, "Wrench", 34, 7.50)};
System.out.println("\nInvoices mapped to description and invoice amount");
Arrays.stream(invoices).sorted(new Comparator<Invoice>() {
@Override
public int compare(Invoice i1, Invoice i2) {
return Double.valueOf(i1.getQuantity() * i1.getPrice()).compareTo(Double.valueOf(i2.getQuantity() * i2.getPrice()));
}
}).map(invoice -> String.format("Description: %-15s Invoice amount: $%,6.2f", invoice.getPartDescription(), (invoice.getQuantity() * invoice.getPrice())))
.forEach(invoice -> System.out.printf("%s%n", invoice));
}
}
Upvotes: -1
Reputation: 101
You have an error in your comparator lambda, it should read
.sorted(Comparator.comparing(invoice -> invoice.getQuantity() * invoice.getPrice()))
rather than
.sorted(Comparator.comparing(invoice.getQuantity() * invoice.getPrice()))
notice missing invoice ->
Upvotes: 3