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