allows interface method to have body
Note: for static method, implementation allowed inside interface
should have only one abstract method ie one functionality.
Ex:Runnable @Comparator .
Interface | arg | return | Method | Example |
---|---|---|---|---|
Function<T,R> |
1 | 1 | .apply() | Function<String, Integer> lengthFunction = str -> str.length(); |
BiFunction<T,U,R> |
2 | 1 | .apply() | BiFunction<Integer, Integer, Integer> sumFunction = (a, b) -> a + b; |
UnaryOperator<T> |
1 | 1 same | .apply() | UnaryOperator |
BinaryOperator<T> |
2 | 1 same | .apply() | BinaryOperator |
Predicate<T> |
1 | 1 bool | .test() | Predicate |
BiPredicate<T> |
2 | 1 bool | .test() | BiPredicate<String, String> areEqual = (a, b) -> a.equals(b); |
Consumer<T> |
1 | no | .accept() | Consumer |
BiConsumer<T,U> |
1 | no | .accept() | BiConsumer<String, String> printTwoStrings = (a, b) -> Sysout(a+”“+b); |
Supplier<T> |
no | 1 | .get() | Supplier |
Primitive Specializations:
generics not needed, applies for all above functions
Ex: IntFunction
anonymous function implements functional interface
Syntax: (argument-list) -> {body}
Legacy Anonymous class:
interface Action { void execute(); }
Action action = new Action() {
@Override
public void execute() {
System.out.println("Action executed!");
}
};
can refer existing method implementations as lambdas, using
::
.
i) staticMethod reference - className::Method
ii) InstanceMethod reference - objectName::Method
iii) constructor reference - className::new
class Person{
public static void main(String[] args){
// Using Instance method reference
BiFunction<Integer, Interger, Double> biFunction = personObj::addNumbers;
biFunction.apply(3,4);
}
Double addNumbers(Interger a, Interger b){
return a+b.doubleValue();
}
}
forcing the caller to handle the null check, this is achieved by wrapping the value with Optional class.
Creation Methods:
Methods | Code | Description |
---|---|---|
of() | Optional.of("Hello"); |
throws NullPointerException if value is null |
ofNullable() | Optional.ofNullable(a.name); |
return Optional |
empty() | Optional.empty() |
Returns empty Optional |
Conditional Methods:
Methods | Code | Description |
---|---|---|
isPresent() | optionalObj.isPresent() |
Checks if value is present |
isEmpty() | optionalObj.isEmpty() |
(Java 9)similar to !isPresent() |
Transformation Methods:
Methods | Code | Description |
---|---|---|
get() | optionalObj.get() |
Throws NoSuchElementException if value not present |
orElse() | optionalObj.orElse(val) |
provided default value if value not present |
orElseGet() | optionalObj.orElseGet(supplier) |
value obtained from supplier function, if value not present |
Consumption Methods:
Methods | Code | Description |
---|---|---|
ifPresent() | optionalObj.ifPresent(consumer) |
execute consumer function if value present |
ifPresentOrElse() | optionalObj.ifPresent(consumer, supplier) |
(Java 9) execute consumer function if value present |
StringJoiner str = new StringJoiner(",","[","]"); //delimiter, prefix, suffix
str.add("muthu").add("rajesh"); // Output : [muthu,rajesh]
helps to process sequences of elements
Source Operation | description |
---|---|
collectionObj.stream() |
Stream from collection object |
mapObj.entrySet.stream() |
Stream from collection Map |
Arrays.stream(array) |
generate IntStream,DoubleStream,LongStream |
str.chars().stream() |
need to use mapToObj(c->(Char)c) |
Stream.empty() |
return empty stream |
Operation | Definition |
---|---|
map() |
Transform each element. |
filter() |
Select elements based on a predicate. |
flatMap() |
combination of flat&map, convert stream of stream into single stream |
flatMapToInt() |
converting nested primitive arrays into a single stream of primitives |
flatMapToObj() |
convert primitive to object |
distinct() |
Remove duplicate for primitive datatypes |
sorted() |
Sort elements. |
limit(5) |
Limit the number of elements. |
skip() |
Skip upto given index |
boxed() |
convert premitive stream into wrapped type |
peek() |
used to debug stream elements |
.sorted(new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
if(o1.getAge() == o2.getAge())
return o1.getName().compareTo(o2.getName());
else if(o1.getAge() > o2.getAge())
return 1;
else return -1;
}
})
Termination Function | Description |
---|---|
forEach(System.out::println) |
Perform an action for each element. |
count() |
Count the number of elements. |
collect(Collectors.toList()) |
Collect elements into a collection. |
findFirst() |
return Optional so handle orElse() |
reduce((a, b) -> a + b) |
return single value, takes BinaryOperator as param |
min() ,max() ,average() ,sum() |
return min/max value(only for primitive) |
anyMatch() ,allMatch() ,noneMatch() |
return boolean if all element matches a predicate |
Collectors Function | Description |
---|---|
To Collections | Collectors.toList() , Collectors.toSet() , Collectors.toMap() |
Joining | Collectors.joining(",") |
Grouping By | Collectors.groupingBy(obj::getYear) Collectors.groupingBy(Map.Entry::getValue) |
Partitioning By | Collectors.partitioningBy(m-> m.getRating() > 3) //map<boolean, obj> |
Averaging | Collectors.averagingInt() , Collectors.averagingDouble() , Collectors.averagingLong() |
Summarizing | Collectors.summarizingInt(), Collectors.summarizingDouble() , Collectors.summarizingLong() |
Reducing | Collectors.reducing() collect(Collectors.reducing(0, Integer::intValue, Integer::sum)); |
Counting | Collectors.counting() |
To Collections | toList() , toSet() , toMap() (from Java 16) |
Syntax Collectors.groupingBy(classifier, Hashmap::new, toList());
Collectors.groupingBy(obj::getYear)
.Collectors.groupingBy(obj::getYear, Collectors.toSet())
.Collectors.groupingBy(obj::getYear, TreeMap::new, Collectors.toSet())
.collect(Collectors.groupingBy(Function.identity(),Collectors.counting());
Stream.of("1","b")
Stream.builder().add(1).build()
Stream.concat(Stream.of("A"), Stream.of("B"))
Stream.generate(random::nextInteger).limit(10)
java 10Stream.iterate(1, n -> n + 1).limit(10)
java9Stream.ofNullable(name)
java9 //return empty stream instead of nullfindAny()
- Find any element (non-deterministic).toArray(String[]::new)
- return arraymapToInt()
- convert obj list into intstreamsummaryStatistics()
- only for primitive streams IntStream, we can use .getMax(), getMin() etcforEachOrdered()
Arrays.stream(input)
.filter(x->x%2==0)
.map(x->x*x)
.sum()
int age = list.stream()
.sorted(Comparator.comparingInt(Employee::getSalary).reversed())
.skip(1).findFirst();
list.stream().collect(
Collection.toMap(Function.identity(),Function.identity()));
2a. Convert a matrix into stream
Arrays.stream(matrixInput).flatMapToInt(Arrays::stream).boxed().collect(Collectors.toList())
2b. Convert intstream into objects
intStream.flatMapToObj(num -> Stream.of("Number-" + num));
listOfStrings.stream()
.flatMap(str -> str.chars())
.mapToObj(ch -> (char) ch)
.collect(Collectors.toSet());
employeeList.stream().sorted(Comparator.comparingInt(Employee::getSalary));
employeeList.stream().sorted(Comparator.comparing(Employee::getName), Comparator.reverseOrder());
Arrays.stream(arr).boxed().sorted(Comparator.reverseOrder());
employeeList.stream().min(Comparator.comparingInt(Employee::getSalary))
Arrays.stream(names).collect(Collectors.joining(","));
studentList.stream().collect(Collectors.groupingBy(Student::getDept)).entrySet().stream().map(value -> value.getKey()).distinct();
studentList.stream().collect(Collectors.groupingBy(Student::getDept, Collectors.counting())).entrySet().stream().max(Map.Entry.comparingByValue()).get();
studentList.stream().collect(Collectors.groupingBy(Student::getDept,Collectors.averagingInt(Student::getAge)));
studentList.stream().collect(Collectors.groupingBy(Student::getDept,Collectors.maxBy(Comparator.comparing(Student::getDept))));
numbers.stream()
.collect(Collectors.partitioningBy(n -> n % 2 == 0));
var result = calculateSum(10, 20);
System.out.println("Sum: " + result); // Output: Sum: 30
public static int calculateSum(int a, int b) {
return a + b;
}
Java 8
Java 11
Java 17
Java 21