Home > database >  Sort by X but print Y
Sort by X but print Y

Time:10-20

In my java program, there are objects of a class called salesperson.

These objects have an attribute called sales and an attribute called name.

I want to compare the sales values to find the largest value and then print out the name of the object that has the highest sale value.

How I did it was

double highSales;
String highSalesString;
highSales=first.getJanSales();
        highSalesString=first.getSName()  " "  first.getTitle();
        if (second.getJanSales()>highSales)
        {
            highSales=second.getJanSales();
            highSalesString=second.getSName()  " "  second.getTitle();
        }
        if (third.getJanSales()>highSales)
        {
            highSales=third.getJanSales();
            highSalesString=third.getSName()  " "  third.getTitle();
        }

I feel like there's a much simpler way to achieve this.

CodePudding user response:

Comparator

You just got to use a Comparator or implement Comparable accordingly.

For example

List<SalesPerson> persons = ...

persons.sort(Comparator.comparingInt(SalesPerson::getSales).reverseOrder());

SalesPerson personWithMostSales = persons.get(0);
System.out.println(personWithMostSales.getName());

If all you want is just this one entry, you do not have to sort the whole list:

SalesPerson personWithMostSales = persons.stream()
    .max(Comparator.comparingInt(SalesPerson::getSales).reverseOrder())
    .orElseThrow();
System.out.println(personWithMostSales.getName());

There is also Collections.max(...) which you can use instead of the stream.


Comparable

If you think that sorting SalesPerson by their sales is a reasonable thing to do by default (a so called natural order), you can also let them implement Comparable accordingly:

public class SalesPerson implements Comparable<? super SalesPerson> {
    ...

    @Override
    public int compareTo(SalesPerson other) {
        return -1 * Integer.compare(sales, other.sales);
    }
}

and then you could put them into a sorted collection such as TreeSet and it would keep them sorted for you already. Note however that such collections usually do not allow that you modify sales while the persons have already been added to the collection.

CodePudding user response:

I want to compare the sales values to find the largest value and then print out the name of the object that has the highest sale value.

I would skip the sorting since all you want seems to be the name of the person that had maximum sales. Assuming your sales people are in a List you can do it as follows:

The record for demo purposes (behaves like a class).

record SalesPerson(String getName, double getSales) {
    @Override
    public String toString() {
        return "Name: "   getName   ", "   "Sales: $"   getSales;
    }
}

Create some data

List<SalesPerson> sales = List.of(new SalesPerson("John", 492.44 ),
        new SalesPerson("Mary", 688.68), new SalesPerson("Bob", 533.22));

  • this streams the SalesPerson instances
  • then using a comparator, finds the maximum based on the sales value.
    max returns an Optional<SalesPerson>.
Optional<SalesPerson> bestSalesPerson = sales.stream()
        .max(Comparator.comparingDouble(SalesPerson::getSales));

if (bestSalesPerson.isPresent()) {
    System.out.println(bestSalesPerson.get());
}

Prints

Name: Mary, Sales: $688.68

If you don't wish to use a stream you can do it with a loop.

  • if the list is not empty assign the first person to best
  • then iterate over the list, comparing each candidate's record to the current best and adjust as required. Extra checks are added in case the list is empty. These can be eliminated if not necessary.
SalesPerson best = null;
if (!sales.isEmpty()) {
    best = sales.get(0);
}
for (int i = 1; i < sales.size(); i  ) {
    SalesPerson candidate = sales.get(i);
    if (candidate.getSales > best.getSales) {
        best = candidate;
    }
}

if (best != null) {
    System.out.println(best);
}
  • Related