简体   繁体   中英

Using streams to find Max

Is the following the recommended way to attempt finding Max with streams?

List<Employee> emps = new ArrayList<>();
emps.add(new Employee("Roy1",32));
emps.add(new Employee("Roy2",12));
emps.add(new Employee("Roy3",22));
emps.add(new Employee("Roy4",42));
emps.add(new Employee("Roy5",52));

Integer maxSal= emps.stream().mapToInt(e -> e.getSalary()).reduce((a,b)->Math.max(a, b));
System.out.println("Max " + maxSal);

It results in a compilation error - what does this mean?

error: incompatible types: OptionalInt cannot be
nverted to Integer
                  Integer maxSal= emps.stream().mapToInt(e -> e.getSalary()).
uce((a,b)->Math.max(a, b));

You can use the method Integer.min in reduce which returns OptionalInt , can be used to get Int (make sure the boundary checks)

using IntStream

int max1 = emps.stream().mapToInt(Employee::getSalary).max().getAsInt();

using IntSummaryStatistics [if you are interested in statistics, like min, max, avg]

IntSummaryStatistics stats = emps.stream().mapToInt(Employee::getSalary).summaryStatistics();
int max2 = stats.getMax();

reduce function

int max3 = emps.stream().mapToInt(Employee::getSalary).reduce(Integer::min).getAsInt();

First, you might shorten your emps initialization with Arrays.asList(T...) like

List<Employee> emps = Arrays.asList(new Employee("Roy1", 32), 
        new Employee("Roy2", 12), new Employee("Roy3", 22),
        new Employee("Roy4", 42), new Employee("Roy5", 52));

Next, you can use OptionalInt.orElseThrow(Supplier<X>) which will get the max value from the List or throw a RuntimeException

int maxSal = emps.stream().mapToInt(Employee::getSalary).max()
        .orElseThrow(() -> new RuntimeException("No Such Element"));
System.out.println("Max " + maxSal);

Finally, you could also reason that no one would accept a negative salary, and use orElse(int) like

int maxSal = emps.stream().mapToInt(Employee::getSalary).max().orElse(-1);
System.out.println("Max " + maxSal);

Answering to your question the problem is that reduce method is going to return an OptionalInt so you need to call the .getAsInt() method if you want to have the Integer value.

    Integer maxSal = emps.stream().mapToInt(e -> e.getSalary())
         .reduce((a,b)->Math.max(a, b)).getAsInt();

In case there is no maximum on the list you will get a NoSuchElementException that you need to deal with.

There is already a max method in IntStream . You don't have to reinvent the wheel:

OptionalInt maxSal = emps.stream().mapToInt(Employee::getSalary).max();
System.out.println("Max " + maxSal);

max returns OptionalInt instead of Integer because there can be no elements in the list. You can use OptionalInt methods to extract the value from it:

maxSal.ifPresent(System.out::println);

Or:

System.out.println(maxSal.orElse(0));

Or:

System.out.println(maxSal.getAsInt());

The latter one may throw an exception, so be careful.

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