Lambda Expressions
Lambda is anonymous function ( function with no name & not being bounded to an identifier).
So what's the big deal?
Everything in Java is around objects so functions cannot exists with objects but with lambda around, you can have functions without any objects and you can pass them as arguments.
Syntax :
(parameters) -> expression
(parameters) -> {statement1; .... ; statementN;}
() -> expression
Functional Interface
It is an interface with exactly one abstract method. You would actually pass in implementation of method as a lambda expression.
For example, java.util.function package provides numerous functional interfaces.
Consumer is a functional interface used for foreach loop.
You can write your own functional interface too.
Lambda Illustrated
For example :
(a,b) -> a + b
integerList.foreach(x -> { if (x > 2) call1(x); else call2(x); });
Static Method Reference
List<String> names = Arrays.asList("name1","name2","name3");
names.forEach(System.out::println);
names.forEach(StringUtils::capitalize);
Instance Reference
method can be invoked using instance reference directly as:
instanceReference::methodname
Constructor Reference
Constructor can be invoked as:
ClassName::new
Unbound non-static reference(By Return Type)
For example ,
String class method toLowerCase()
Usage : ClassName :: methodName
String str ="abc";
Now, toLowerCase can be invoked as
s-> s.toLowerCase()
s:: toLowerCase
String ::toLowerCase
======================================
Stream
Process collection of objects . This method can be invoked on any Class that implements Collection Interface.
Stream has a source, intermediate & Terminal operation.
Collection.stream() - Returns Sequential Stream
Collection.parallelStream() - Returns Parallel Stream( Can also be used for sequential stream)
Stream can also be created as :
1> Empty Stream
Stream.empty() - > Empty String
2> Stream.generate(Supplier)
Stream.generate(new Random()::nextInt).limit(15)
15 elements generated
3> Stream.iterate(Seed, UnaryOperator)
Stream.iterate(0, n->n+1).limit(20)
4> Stream.of()
Stream.of(1) or Stream.of("a","b","c")
5> Arrays.stream
String[] arr = new String[]{"str1","str2","str3"};
Arrays.stream(arr)
6> Stream.builder()
Stream.<String>builder().add("str1")
.add("str2").build();
7> From Primitives
IntStream.rangeClosed(startInclusive,endInclusive)
IntStream.range(startInclusive,endExclusive)
8> From file
Files.lines(filePath)
9> From String
Pattern.compile(";").splitAsStream("a";"b";"c")
String str = "some String";
IntStream it = str.chars();
10> Concatenates 2 Streams
Stream.concat(stream1, stream2)
Something Important about Stream
Stream is one time kind of operation so once executed, it cannot be referenced again unless it is re-executed.
For example,
Stream <Integer> integerStream = Stream.of(1, 2,3)
.filter(x -> x > 1);
integerStream.count() ; //executes well
//At this point stream has already reached its final stage or //terminal hence following statement will throw exception
integerStream.findAny() ;// throws IllegalStateException
WorkAround :
List<Integer> integerList = Stream.of(1, 2,3)
.filter(x -> x > 1).collect(Collectors.toList());
integerList.stream().count();
integerList.stream().findAny() ;// Valid
Stream Operations
Returning Stream:
Let's look at methods that returns back another stream ( Please also look at Static Methods returning Stream above) :
stream.filter(Predicate)
Examples :
strlist.stream().filter(str -> str.matches("MyName")).collect(Collectors.toList());
Get a Employee if Found :
employeeList.stream().filter(emp-> emp.getName().equals("Milind"))
.findAny() //Return a Employee Wrapped under Optional
.OrElse(null);
employeeList1.stream()
.filter(employeeList2::contains).collect(Collectors.toList());
Here Employee must override equals & hashcode otherwise it will return empty as they are from different memory storage
stream.map(function)
employeeList.stream().filter(
emp-> emp.getName().equals("Milind"))
.map(Employee::getName)
.findAny() //Returns employee's name under Optional
.orElse(null);
employeeList.stream()
.map(Employee::getName)
.collect(Collectors.toList())
stream.flatmap(function)
Basically flats the array/set/list into Stream of that Object
employeeList.stream()
.map(x -> x.getPreviousEmployers()) //Stream<List<Employers>>
.flatmap(x-> x.stream())
.distinct()
.collect(Collectors.toList());
stream.limit(number)
employeeList.stream()
.sorted().limit(1).findAny();
stream.distinct()
employeeList.stream()
.distinct().collect(Collectors.toList());
stream.peek(someaction)
employeeList.stream()
.map(Employee:: getName)
.peek(System.out::println);
stream.skip(firstn)
employeeList.stream()
.skip(2)..map(Employee:: getName)
.peek(System.out::println);
stream.sorted(), stream.sorted(Comparator)
employeeList.stream()
.sorted().limit(1).findAny();
Returning Actual Object or wrapped in Optional:
stream.findAny() - Optional<T>
employeeList.stream()
.sorted().limit(1).findAny();
stream.findFirst()- Optional<T>
employeeList.stream()
.sorted().limit(1).findFirst();
stream.max(Comparator)- Optional<T>
Integer maxEmpId =
employeeList.stream()
.map(Employee::getId)
.max(Integer :: compare)
.get();
stream.min(Comparator)- Optional<T>
Integer minEmpId =
employeeList.stream()
.map(Employee::getId)
.min(Integer :: compare)
.get();
stream.reduce(binaryOperator) - Optional<T>
employeeList.stream()
.filter(emp -> emp.getDept().equals("IT")
.map(Employee::getSalary)
.reduce((x,y)-> x+y).
.ifPresent(System.out::println);
stream.reduce(identity,binaryOperator) - T
long initialValue= 10000L; //Misc Expenses
long totalExpenses = employeeList.stream()
.filter(emp -> emp.getDept().equals("IT")
.map(Employee::getExpenses)
.reduce(initialValue, (x,y)-> x+y).
Returning Other Types :
stream.reduce(identity,bifunction,binaryOperator) - IdentityType
int[] intArray = {4,3,2};
int result =
Arrays.stream(intArray)
.boxed()
.reduce(1, (a,b) -> a * b, (d,e)-> d* e);
System.out.println(result); //prints 24
int result =
Arrays.stream(intArray)
.boxed()
.parallel()
.reduce(1, (a,b) -> a * b, (d,e)-> d* e);
stream.collect (Collector<R>) - R
Map<Employee.Gender, Long> byGenders = employeeList.stream()
.filter(emp -> emp.getDept().equals("IT")
.collect(Collectors.groupingBy(x-> x.getGender(), Collectors.counting()));
stream.collect(Supplier, accumulator, combiner) - R
Example1:
List<String> list = Arrays.asList("s1", "s2", "s3","s4","s5","s6");
List<String> list1 = list.stream().map(Object::toString).collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
System.out.println(list1);
String s = list.stream().collect(StringBuilder::new,
(sb, s1) -> sb.append(",").append(s1),
(sb1, sb2) -> sb1.append("->").append(sb2.append("]"))).toString();
System.out.println(s);
Output : ,s1,s2,s3,s4,s5,s6
String s = list.parallelStream().collect(StringBuilder::new,
(sb, s1) -> sb.append(",").append(s1),
(sb1, sb2) -> sb1.append("->").append(sb2.append("]"))).toString();
System.out.println(s);
Output : ,s1->,s2->,s3]]->,s4->,s5->,s6]]]
stream.allMatch(Predicate) - boolean
stream.anyMatch(Predicate) - boolean
stream.noneMatch(Predicate) - boolean
Other Operations:
stream.count() - long
stream.forEach(Consumer action) - void
stream.forEachOrdered(Consumer action) - void
stream.ToArray() - Object[]
stream.toArray(IntFunction A[]) - A[]
Additional :
stream.mapToDouble/ToInt/ToLong
stream.flatmapToDouble/ToInt/ToLong
No comments:
Post a Comment