Wednesday, 24 June 2020

Power of Lambda - II

There is a very common interview question or you can say common requirement in our daily coding life we come across.

"Write a Java program to count the occurrence of each character in a string"

There are various type of logics to achieve this
  • using array
  • using Java maps etc...
But here I am going to demonstrate how it can be achieved in a smarter way using the power of lambda.
String statement = "A quick brown fox jumps over the lazy dog!";
final Map<Character, Integer> charOccurrenceMap = new HashMap<>();
statement.chars()
.forEach(ch -> charOccurrenceMap
.merge((char)ch, 1, (prevValue, value) -> prevValue + value));
System.out.println(charOccurrenceMap);
Output
{A=1,  =8, !=1, a=1, b=1, c=1, d=1, e=2, f=1, g=1, h=1, i=1, j=1, k=1, l=1, m=1, n=1, o=4, 
p=1, q=1, r=2, s=1, t=1, u=2, v=1, w=1, x=1, y=1, z=1}

Realtime Example

"Let's you have a collection of customer requests and want to count number of 
requests initiated by each account"
class CustomerRequest {
long accNo;
String reqPayload;
// some other details
public CustomerRequest(long accNo, String reqPayload) {
this.accNo = accNo;
this.reqPayload = reqPayload;
}
//getter and setter
}
public class Main {
public static void main(String[] args) {
List<CustomerRequest> requestList = generateDummyCustomerRequests();
final HashMap<Long, Integer> requestCountMap = new HashMap<>();
requestList
.stream()
.map(CustomerRequest::getAccNo)
.forEach(accNumber -> requestCountMap
.merge(accNumber, 1, (prevCount, value) -> prevCount + 1));
System.out.println(requestCountMap);
}

// this is a helper method to build dummy customer requests
private static List<CustomerRequest> generateDummyCustomerRequests() {
final ArrayList<CustomerRequest> customerRequests = new ArrayList<>();
customerRequests.add(new CustomerRequest(123, "payload 1"));
customerRequests.add(new CustomerRequest(345, "payload 2"));
customerRequests.add(new CustomerRequest(123, "payload 3"));
customerRequests.add(new CustomerRequest(456, "payload 4"));
customerRequests.add(new CustomerRequest(345, "payload 5"));
return customerRequests;
}
}
Output
{456=1, 345=2, 123=2}
Here is what java documentation of Map.merge() method says:
If the specified key is not already associated with a value or is
associated with null, associates it with the given non-null value.
Otherwise, replaces the associated value with the results of the given
remapping function, or removes if the result is {@code null}. This
method may be of use when combining multiple mapped values for a key.
For example, to either create or append a {@code String msg} to a
value mapping: map.merge(key, msg, String::concat)
How it works internally is:
V oldValue = map.get(key);
V newValue = (oldValue == null) ? value :
             remappingFunction.apply(oldValue, value);
if (newValue == null)
    map.remove(key);
else
    map.put(key, newValue);
I hope it helps to understand how powerful is Java lambda and stream API. Please start 
using in your daily coding. Please feel free to share your comment and feedback.

No comments:

Post a Comment