Hello readers, in this blog, I am going to show some scratch work, based on the recent interview trends in Test Automation. These days most organizations are expecting people to code using Java 8 style, than Java 6 style, and there is nothing wrong in it, Java has been evolving and helping us optimizing our coding effort. In case, you are a test automation professional and yet to upgrade your coding style to Java 8, then this article will surely help you to break the ice.
No more boring texts to read :) , the complete program is self-explanatory. Major highlight is the use of generic type filter functions, Bi-functions, Optional's and generator functions.
package springboot.webdriver.cucumber;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiFunction;
import java.util.function.Function;
public class Miscellaneous {
public static void main(String[] args) {
//Creating a linked list. Remember this data-structure does not
// allocate contiguous space like array-list. This linked
// list will be used throughout most part of the below code.
LinkedList<Integer> objSearchableLinkedList = new LinkedList<Integer>();
objSearchableLinkedList.add(5);
objSearchableLinkedList.add(1);
objSearchableLinkedList.add(4);
objSearchableLinkedList.add(3);
objSearchableLinkedList.add(2);
//Creating an object of this class, will be used to call
// non-static methods
Miscellaneous practiceLinkedList = new Miscellaneous();
//This map will be used to showcase some Java8 steam() and
// filter() concepts
Map<String,String> objMap = new HashMap<>();
objMap.put("Tamil Nadu","Chennai");
objMap.put("Karnataka","Bengaluru");
objMap.put("West Bengal","Kolkata");
//To diversify the examples creating this List<Integer>.
// Remember we are
//using List<T> interface object, rather than Array-List /
// Linked-List
//reason behind it is, later we can store array-list or
// linked-list vales in it
int[] pval= {11,20,21,22};
List<Integer> objAlist = Arrays.stream(pval).boxed().toList();
//The element() method always returns the HEAD or the first element
//of the LinkedList. The peek() method also returns the same
System.out.println("element() method returns the first element" +
" of the linked-list, peek() method also does the same "
+ objSearchableLinkedList.element());
//Find if a given number is present in the Linked List and return
// its index, in Java 6 style
System.out.println("The Linked-list is hardcoded with values" +
" between 1 to 5. Now enter a number to be searched" +
" in the linked-list: ");
//You need to enter the value in the execution prompt
//for the program to resume.
int input = new Scanner(System.in).nextInt();
System.out.println("Output returned by Java 6 style:");
practiceLinkedList.findInputInLinkedList(objSearchableLinkedList,
input);
System.out.println("Output returned by Java 8 style:");
//Below example will do the same in Java 8 style
practiceLinkedList.findInputInLinkedListJava8(
objSearchableLinkedList,
input);
//Sort and display the integer Linked-List values in Ascending order
System.out.println("Sorted values of Linked-List in ascending" +
" order: "
+ objSearchableLinkedList.element());
objSearchableLinkedList.sort(Comparator.
comparingInt(Integer::intValue));
objSearchableLinkedList.forEach(System.out::println);
//sort and display elements from a List of integer in reverse order
System.out.println("Sorted values of List in descending " +
"order/reverse: "
+ objSearchableLinkedList.element());
List<Integer> objList = objAlist.stream().sorted(Comparator.
reverseOrder())
.toList();
objList.forEach(System.out::println);
//Using BiFunction and generic filter method to find integers in
// a LinkedList whose values are greater than 2
List<Integer> result1 = practiceLinkedList
.filterList(objSearchableLinkedList,2,
practiceLinkedList::filterByValue);
System.out.println("BiFunction on Integer Linked-List output: "
+result1.toString());
//Using BiFunction and generic filter method to find a string in
// a Map values, where the string length is less than or equal
// to 7
List<String> result2 = practiceLinkedList.filterMap(
objMap,7,practiceLinkedList::filterByStringLength
);
result2.forEach(a->System.out.println("BiFunction on map" +
" output: "+a));
//Below is a use case for using Optional and using it with streams
String testString = new Random().nextInt(1,5)%2==0
?"hello":null; //Generating random string value
Optional<String> optString = Optional.ofNullable(testString);
assert(optString.isPresent());
optString.ifPresent(val -> System.out.println("Length of String: "
+val.length()));
Optional<String> optString2 = optString.stream().findFirst();
optString2.ifPresent(System.out::println);
//Below is use case for Generator function
List<Integer> objIntegerList = Arrays.asList(1,2,2); //input
//Below are generator functions, which we are going to chain together
Function<List<Integer>, Integer> function = (val)->val
.stream().map(X-> X*2)
.mapToInt(B->B).distinct().sum();
Function<Integer,Integer> function2 = (val1) -> val1 *10;
Function<Integer,Integer> function3 = (val2) -> val2*100;
//Chaining generator functions call
Integer result = function3.andThen(function2).apply
(function.apply(objIntegerList));
System.out.println("Result: " + result);
}
/**
* This method will be supplied as parameter in place of the
* BiFunction. The BiFunction will be responsible to apply
* this method to the inputs to the generic filterList method
* and will return the output
* @param val
* @param size
* @return
*/
private Integer filterByValue(Integer val, Integer size) {
if (val > size) {
return val;
} else {
return null;
}
}
//Another support method to be used as BiFunction parameter
private String filterByStringLength(String val, Integer size) {
if (val.length()<=size) {
return val;
} else {
return null;
}
}
/**
* This is a generic type implementation of a custom filter method.
* Why do we need one? Well, the stream().filter() methods can take
* only one variable as argument. If we need two variables as
* argument, then we need to use BiFunction<T, U, R> function().
* If you study the below method, the first argument takes List<T>,
* Second argument will determine the type by the passed value,
* and the third argument is a BiFunction.
* @param list1
* @param condition
* @param func
* @param <T>
* @param <U>
* @param <R>
* @return
*/
protected <T, U, R> List<R> filterList(List<T> list1,
U condition, BiFunction<T, U, R> func) {
//If you want to return different type of value,
//you can modify the return type of result here
List<R> result = new ArrayList<>();
for (T t : list1) {
//The apply(t,condition) method is a special method
// introduced by Java 8 Functional programming
R apply = func.apply(t, condition);
if (apply != null) {
result.add(apply);
}
}
return result;
}
//Another generic type function, which will be applied to a Map
protected <T, U, R> List<R> filterMap(Map<T,T> map1,
U condition, BiFunction<T, U, R> func) {
//If you want to return different type of value,
//you can modify the return type of result here
List<R> result = new ArrayList<>();
for (T t : map1.values()) {
//The apply(t,condition) method is a special method
// introduced by Java 8 Functional programming
R apply = func.apply(t, condition);
if (apply != null) {
result.add(apply);
}
}
return result;
}
//This method uses Java 6 style syntax to find and return an element
// from the linked list
public void findInputInLinkedList(LinkedList<Integer> objLinkedList,
Integer input)
{
ListIterator<Integer> objIterator= objLinkedList
.listIterator(0);
AtomicBoolean notFoundFlag = new AtomicBoolean();
notFoundFlag.set(true);
System.out.println("Remember Peek value in Linked List " +
" never changes, until a pollFirst() method is executed" +
" so, current peek always returns the Head:" +
objLinkedList.peek());
while(objIterator.hasNext()) {
var value = objIterator.next();
if(Objects.equals(value, input)) {
notFoundFlag.set(false);
System.out.println("input value present in the linked list: "
+ input + ", its index is: "+objLinkedList.
indexOf(value));
break;
}else{
notFoundFlag.set(true);
}
}
if(notFoundFlag.get()) {
System.out.println("input value is NOT present in the linked list");
}
}
//This method uses Java 8 style syntax to find and return element
//from the linked list
public void findInputInLinkedListJava8(LinkedList<Integer> objLinkedList,
Integer input)
{
//Atomic values are mutable, and accessible from Lamda functions/methods
AtomicInteger i = new AtomicInteger();
int indexOfElement = objLinkedList.stream()
.peek(val -> i.incrementAndGet())
.anyMatch(target -> Objects.equals(target, input)) ?
i.get() - 1 : -1;
if(indexOfElement >= 0)
System.out.println("input value present in the linked list: "
+ input + ", its index is: " + indexOfElement);
else {
System.out.println("input value is NOT present in the linked list");
}
}
}
Here are the outputs:
element() method returns the first element of the linked-list, peek() method also does the same 5
The Linked-list is hardcoded with values between 1 to 5. Now enter a number to be searched in the linked-list:
4
Output returned by Java 6 style:
Remember Peek value in Linked List never changes, until a pollFirst() method is executed so, current peek always returns the Head:5
input value present in the linked list: 4, its index is: 2
Output returned by Java 8 style:
input value present in the linked list: 4, its index is: 2
Sorted values of Linked-List in ascending order: 5
1
2
3
4
5
Sorted values of List in descending order/reverse: 1
22
21
20
11
BiFunction on Integer Linked-List output: [3, 4, 5]
BiFunction on map output: Chennai
BiFunction on map output: Kolkata
Length of String: 5
hello
Result: 6000
Process finished with exit code 0