Java 8 lambda for selecting top salary employee for each department

You can do that with a grouping collector: Map<String, Employee> topEmployees = allEmployees.stream() .collect(groupingBy( e -> e.department, collectingAndThen(maxBy(comparingInt(e -> e.salary)), Optional::get) )); with the static imports import static java.util.Comparator.comparingInt; import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.maxBy; This code creates a Stream of all the employees and groups them with their department with the … Read more

How to get multiple values from an object using a single stream operation?

JDK 12 and above has Collectors.teeing (webrev and CSR), which collects to two different collectors and then merges both partial results into a final result. You could use it here to collect to two IntSummaryStatistics for both the x coordinate and the y coordinate: List<IntSummaryStatistics> stats = points.stream() .collect(Collectors.teeing( Collectors.mapping(p -> p.x, Collectors.summarizingInt()), Collectors.mapping(p -> … Read more

Why does a Java Lambda which throws a Runtime Exception require brackets?

The Java Language Specification describes the body of a lambda expression A lambda body is either a single expression or a block (§14.2). This, however, throw new IllegalArgumentException(“fail”) is the throw statement, not an expression. The compiler therefore rejects it as the lambda expression’s body. You can go down the rabbit hole and learn what … Read more

Group sequences of values

Unfortunately, the Stream API is not very well suited to tackle problems that involve dependant operations on the Stream element, like this one. However, you can use the StreamEx library for this: public static void main(String[] args) { IntStream seq = IntStream.of(1, 2, 3, -1, -1, 1, 2, 1, 2); IntUnaryOperator next = i -> … Read more

Creating String representation of lambda expression [duplicate]

The simplest thing I could come up with is creating a “named predicate” that gives your predicates a name or description, basically anything that will be useful as a toString: public class NamedPredicate<T> implements Predicate<T> { private final String name; private final Predicate<T> predicate; public NamedPredicate(String name, Predicate<T> predicate) { this.name = name; this.predicate = … Read more

Perform operation on n random distinct elements from Collection using Streams API

The shuffling approach works reasonably well, as suggested by fge in a comment and by ZouZou in another answer. Here’s a generified version of the shuffling approach: static <E> List<E> shuffleSelectN(Collection<? extends E> coll, int n) { assert n <= coll.size(); List<E> list = new ArrayList<>(coll); Collections.shuffle(list); return list.subList(0, n); } I’ll note that using … Read more

Java 8’s orElse not working as expected

The arguments for a method are always evaluated before the method is called. You want orElseGet which takes a Supplier that will only be invoked if the Optional is not present: private Field getField(Class<?> clazz, String p) { return Arrays.stream(clazz.getDeclaredFields()) .filter(f -> p.equals(f.getName())) .findFirst() .orElseGet(() -> getField(clazz.getSuperclass(), p)); }

Cannot use Java 8 method with lambda arguments without specifying type arguments

Holger had the best answer in the comment section in my opinion: This is a known limitation of Java 8’s type inference: it doesn’t work with chained method invocations like genericFactoryMethod().build(). Thanks! About my API, I will specify the functions before using them as arguments, like this: Function<Entry<String, Set<String>>, String> keyMapper = Entry::getKey; Function<Entry<String, Set<String>>, … Read more