Сортировать по X, но выводить Y

java #sorting #max

#java #сортировка #макс

Вопрос:

В моей Java-программе есть объекты класса called salesperson .

У этих объектов есть вызываемый атрибут sales и вызываемый атрибут name .

Я хочу сравнить значения продаж, чтобы найти наибольшее значение, а затем распечатать имя объекта с наибольшей стоимостью продажи.

Как я это сделал, было

 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();
        }
 

Я чувствую, что есть гораздо более простой способ добиться этого.

Ответ №1:

Comparator

Вам просто нужно использовать Comparator или реализовать Comparable соответствующим образом.

Например

 List<SalesPerson> persons = ...

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

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

Если все, что вам нужно, это только одна запись, вам не нужно сортировать весь список:

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

Существует также Collections.max(...) , который вы можете использовать вместо потока.


Comparable

Если вы считаете, что сортировка SalesPerson по их sales разумно выполнять по умолчанию (так называемый естественный порядок), вы также можете позволить им реализовать Comparable соответствующим образом:

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

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

и тогда вы могли бы поместить их в отсортированную коллекцию, такую как TreeSet , и она уже сохранит их отсортированными для вас. Однако обратите внимание, что такие коллекции обычно не позволяют изменять sales , пока лица уже добавлены в коллекцию.

Ответ №2:

Я хочу сравнить значения продаж, чтобы найти наибольшее значение, а затем распечатать имя объекта с наибольшей стоимостью продажи.

Я бы пропустил сортировку, поскольку все, что вам нужно, — это имя человека, у которого было максимальное количество продаж. Предполагая, что ваши продавцы находятся в списке, вы можете сделать это следующим образом:

Запись для демонстрационных целей (ведет себя как класс).

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

Создайте некоторые данные

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

 
  • это передает экземпляры продавца
  • затем, используя компаратор, находит максимум на основе стоимости продаж.
    max возвращает Optional<SalesPerson> .
 Optional<SalesPerson> bestSalesPerson = sales.stream()
        .max(Comparator.comparingDouble(SalesPerson::getSales));

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

С принтами

 Name: Mary, Sales: $688.68

 

Если вы не хотите использовать поток, вы можете сделать это с помощью цикла.

  • если список не пуст, назначьте первого человека best
  • затем выполните итерацию по списку, сравнивая записи каждого кандидата с текущими лучшими и корректируйте по мере необходимости. Дополнительные проверки добавляются в случае, если список пуст. Они могут быть устранены, если в этом нет необходимости.
 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);
}