All 15 Functional Interfaces & Method References questions
More in Functional Interfaces & Method References
Advertisement
Back to results for “Collections”
Java › Functional Interfaces & Method References

What is the difference between a Consumer<T> and a BiConsumer<T,U>, and how would you use BiConsumer for operations needing two inputs but no return value, such as Map.forEach()?

Intermediate

Answer

Consumer<T> accepts a single argument and performs a side effect with no return value (accept(T t)); BiConsumer<T,U> accepts two arguments and similarly performs a side effect with no return value (accept(T t, U u)) -- Map's forEach(BiConsumer<K,V>) method is a canonical use case, letting you process each key-value pair together in one lambda without needing to manually iterate entrySet() and destructure each Map.Entry yourself.
Map<String, Integer> ages = Map.of("Alice", 30, "Bob", 25);

// BiConsumer used directly via Map.forEach()
ages.forEach((name, age) -> System.out.println(name + " is " + age + " years old"));

// Equivalent using an explicit BiConsumer variable
BiConsumer<String, Integer> printer = (name, age) -> System.out.println(name + ": " + age);
ages.forEach(printer);
Real-world example A logging utility processing a Map<String, List<String>> of grouped validation errors uses Map.forEach() with a BiConsumer lambda to print each field name alongside its associated list of error messages, avoiding the more verbose alternative of manually iterating entrySet() and calling getKey()/getValue() on each entry.

Common follow-ups: What's the equivalent BiFunction and BiPredicate interfaces, and what scenarios call for each?;Why doesn't Consumer have an andThen()-based way to short-circuit, unlike Predicate's and()/or()?