Sunday, 14 June 2020

Stream - filter(), map(), collect(), min(), max()


1) Filter:

filter() is used to filter data in stream. This method takes a Predicate as parameter. The Predicate interface contains a function called test() which the lambda expression passed as parameter is matched against. In other words, the lambda expression implements the Predicate.test() method.

stream.filter( item -> item.startsWith("o") ); 

It takes a single parameter and returns a boolean. If you look at the lambda expression above, you can see that it takes a single parameter item and returns a boolean - the result of the item.startsWith("o") method call.


2) Map:
map() is used to perform transformation for the items in a collection to other objects.

items.stream().map( item -> item.toUpperCase() )

In above stream items in stream is transformed to uppercase.

3) Collect:
when collect() method is invoked, the filtering and mapping will take place and the object resulting from those actions will be collected.

List<String> filtered = items.stream().filter( item -> item.startsWith("o") )
                                    .collect(Collectors.toList());

4) Min and Max:
The min() and max() methods take a Comparator as parameter. The Comparator.comparing() method creates a Comparator based on the lambda expression passed to it. In fact, the comparing() method takes a Function which is a functional interface suited for lambda expressions. It takes one parameter and returns a value.

The min() and max() methods return an Optional instance which has a get() method on, which you use to obtain the value. In case the stream has no elements the get() method will return null.

String shortest = items.stream()
        .min(Comparator.comparing(item -> item.length()))
        .get();

Inbuilt method:
List<Integer> list = Arrays.asList(-9, -18, 0, 25, 4); 
  
/* Using stream.min() to get minimum element according to provided Integer Comparator */
Integer var = list.stream().min(Integer::compare).get(); 
System.out.print(var); 

Wednesday, 10 June 2020

Stream Operations

When ever we operate on data we will have basic CURD operation. Let's see how we are doing CURD in streams:

1) Create a stream:

List<Integer> lstInt = Arrays.asList(1,2,3,4,5,6,7,8);

lstInt.stream().forEach(System.out::println);

Stream has 2 steps - Configuring and Processing

In configuring phase, we would apply non terminal operations - filters and mappings

In processing phase, operation applied and result is produced

List<Integer> lstInt = Arrays.asList(1,2,3,4,5,6,7,8);

lstInt.stream().filter( item -> item > 5 ).forEach(System.out::println);

filter() - non terminal operations
forEach() - terminal operations

2) Update a stream: Updation is not removing actual elements from stream but filtered and givin what is expected. Once terminal operation is specified we can't use them again

3) Read a stream: All terminal operation which prints out elements are read operation - forEach(), collect()

4) Delete stream: 
  removeIf uses an Iterator to iterate over the list and match the elements using the predicate.
  removeAll uses a simple for-loop to remove all the matching elements in the list.

Non-Terminal Operations:
filter()
map()
flatMap()
distinct()
limit()
peek()
Terminal Operations:
anyMatch()
allMatch()
noneMatch()
collect()
count()
findAny()
findFirst()
forEach()
min()
max()
reduce()
toArray()

Java Streams

Why we need streams in java?

1) A stream does not store data. An operation on a stream does not modify its source, but simply produces a result. Without stream we need to have iterator or foreach to get item in collection.

2) You can add to or remove elements from collections. But, you can’t add to or remove elements from streams. Stream consumes a source, performs operations on it and returns a result.

3) Streams can be traversed only once. If you traverse the stream once, it is said to be consumed. To traverse it again, you have to get new stream from the source again. But, collections can be traversed multiple times.

List<Integer> numbers = Arrays.asList(4, 2, 8, 9, 5, 6, 7);
Stream<Integer> numbersGreaterThan5 = numbers.stream().filter(i -> i > 5);
         
//Traversing numbersGreaterThan5 stream first time
numbersGreaterThan5.forEach(System.out::println);
         
//Second time traversal will throw error  
//Error : stream has already been operated upon or closed   
numbersGreaterThan5.forEach(System.out::println);

4) Collections elements are computed at the beginning itself. But, streams are lazily constructed i.e intermediate operations are not evaluated until terminal operation is invoked.

//Here, not all numbers are evaluated.
//numbers are evaluated until 3 numbers >= 5 are found.
Arrays.asList(4, 2, 8, 9, 5, 6, 7).stream().filter(i -> i >= 5).limit(3).forEach(System.out::println);

Operations done by streams are classified as - filtering, matching and mapping

Sunday, 24 May 2020

Comparator and Comparable interface:



Java String class implements the Comparable interface, you can sort them in their natural order, using the Collections sort() method.

if you want to sort the user defined objects in another order than their compare() implementation, then you need to use a Comparator implementation (java.util.Comparator)

Usual Implementation in Java 7:

import java.util.*;
public class Main
{
public static void main(String[] args) {
    List<Car> list = new ArrayList<>();

            list.add(new Car("Volvo V40" , "XYZ 201845", 5));
            list.add(new Car("Citroen C1", "ABC 164521", 4));
                ist.add(new Car("Dodge Ram" , "KLM 845990", 2));
Collections.sort(list, new BrandCompare());
for(Car lst: list){
    System.out.println(lst.brand);
}
}
}
class Car{
    public String brand;
    public String numberPlate;
    public int noOfDoors;

    public Car(String brand, String numberPlate, int noOfDoors) {
        this.brand = brand;
        this.numberPlate = numberPlate;
        this.noOfDoors = noOfDoors;
    }
}
class BrandCompare implements Comparator<Car>{
    
    public int compare(Car car1, Car car2) {
        return car1.brand.compareTo(car2.brand);
    }
}
class PlateCompare implements Comparator<Car>{
    
    public int compare(Car car1, Car car2) {
        return car1.numberPlate.compareTo(car2.numberPlate);
    }
}

Implementation in external class:

List<Car> list = new ArrayList<>();

list.add(new Car("Volvo V40" , "XYZ 201845", 5));
list.add(new Car("Citroen C1", "ABC 164521", 4));
list.add(new Car("Dodge Ram" , "KLM 845990", 2));

Comparator<Car> carBrandComparator = new Comparator<Car>() {
    @Override
    public int compare(Car car1, Car car2) {
        return car1.brand.compareTo(car2.brand);
    }
};

Collections.sort(list, carBrandComparator);


Implementation in external class using lambda experession:

List<Car> list = new ArrayList<>();

list.add(new Car("Volvo V40" , "XYZ 201845", 5));
list.add(new Car("Citroen C1", "ABC 164521", 4));
list.add(new Car("Dodge Ram" , "KLM 845990", 2));


Comparator<Car> carBrandComparatorLambda      =
    (car1, car2) -> car1.brand.compareTo(car2.brand);

Comparator<Car> carNumberPlatComparatorLambda =
    (car1, car2) -> car1.numberPlate.compareTo(car2.numberPlate);

Comparator<Car> carNoOfDoorsComparatorLambda  =
    (car1, car2) -> car1.noOfDoors - car2.noOfDoors;

Collections.sort(list, carBrandComparatorLambda);
Collections.sort(list, carNumberPlatComparatorLambda);
Collections.sort(list, carNoOfDoorsComparatorLambda);

We can also make use of getter method in bean to specify comparator field:

class Car{
    public String brand;
    public String numberPlate;
    public int noOfDoors;
    
    public String getBrand(){
        return this.brand;
    }
}

List<Car> list = new ArrayList<>();

list.add(new Car("Volvo V40" , "XYZ 201845", 5));
list.add(new Car("Citroen C1", "ABC 164521", 4));
list.add(new Car("Dodge Ram" , "KLM 845990", 2));

Comparator<Car> brandCompare =Comparator.comparing(Car::getBrand);  
 Collections.sort(al,brandCompare); 

Thursday, 21 May 2020

Running time of Java Iterator


Happy to see you after a long time. I have started working on Java collections and I have tried measuring retrieval time for each collection iterator types using 1000 records in Java 8 and found below time(in seconds) for iteration.

 List Name\Iterator types Iterator    Foreach For loop
 Array List 0.0856     0.044 0.0491
 Linked List 0.02867 0.0504 0.0467
 Vector 0.0342 0.0444 0.0584
 
I have also tried to use for-each lambda expression, this gives below time for each list collection:

Vector - 0.17455
Linked List - 0.17691
Array List - 0.18599

Retrieval time for binarySearch() in collection:

Vector - 0.00377
Linked List - 0.00377
Array List - 0.01069

Wednesday, 23 November 2016

Monday, 31 October 2016

Short Intro on Typescript


down vote
accepted

TypeScript is a superset of JavaScript which primarily provides optional static typing, classes and interfaces. One of the big benefits is to enable IDEs to provide a richer environment for spotting common errors as you type the code.

As an example, here's some TypeScript (you can play with this in the TypeScript Playground)
class Greeter {
    greeting: string;
    constructor (message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}  
And here's the JavaScript it would produce
var Greeter = (function () {
    function Greeter(message) {
        this.greeting = message;
    }
    Greeter.prototype.greet = function () {
        return "Hello, " + this.greeting;
    };
    return Greeter;
})();
Notice how the TypeScript defines the type of member variables and class method parameters. This is removed when translating to JavaScript, but used by the IDE and compiler to spot errors, like passing a numeric type to the constructor.
It's also capable of inferring types which aren't explicitly declared, for example, it would determine the greet() method returns a string.

TypeScript makes typing a bit easier and a lot less explicit by the usage of type inference. For example: var x = "hello" in TypeScript is the same as var x : string = "hello". The type is simply inferred from its use. Even it you don't explicitly type the types, they are still there to save you from doing something which otherwise would result in a run-time error.
TypeScript is optionally typed by default. For example function divideByTwo(x) { return x / 2 } is a valid function in TypeScript which can be called with any kind of parameter, even though calling it with a string will obviously result in a runtime error. Just like you are used to in JavaScript. This works, because when no type was explicitly assigned and the type could not be inferred, like in the divideByTwo example, TypeScript will implicitly assign the type any. This means the divideByTwo function's type signature automatically becomes function divideByTwo(x : any) : any. There is a compiler flag to disallow this behavior: --noImplicitAny. Enabling this flag gives you a greater degree of safety, but also means you will have to do more typing.