vasanth0989 / prep-myself

0 stars 0 forks source link

Streams #11

Open vasanth0989 opened 9 months ago

vasanth0989 commented 9 months ago
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class TestMain {

    public static void main(String[] args) throws Exception {
        // Streams
        // Java
        List<Employee> employees = new ArrayList<>();
        employees.add(new Employee("John", 19));
        employees.add(new Employee("Smith", 24));
        employees.add(new Employee("Smith", 25));

        int sum = 0;
        //for Each loop is available from Java 5
        for (Employee employee : employees) {
            sum += employee.getAge();
        }

        long count = employees.stream().mapToInt(Employee::getAge).sum();
        System.out.println("Sum is:" + sum);
        System.out.println("count is:" + count);

        employees.stream()
                .map(e -> e.getName())
                .map(s -> {
                    String val = s.toUpperCase();
                    String text = val.substring(0, 1);
                    return text;
                })
                .forEach(v -> System.out.println("Emp Name:" + v));

        // method reference - is a shortcut way of writing Lambda expression
        employees.stream()
                .map(e -> e.getName())
                // .map(s -> s.toUpperCase())
                .map(String::toUpperCase)
                .forEach(System.out::println);

        // Implicit final
        int ageBar = 18;

//        employees.stream().forEach( emp -> {
//            // This errors out because you are tyring to modify the value which is declared outside the scope '{}'
//            ageBar = 22;
//        });

        employees.stream().forEach(emp -> {
            int internalAgeBar = 17;
            // This works it is declared within the scope
            internalAgeBar = 29;
        });

        // Intermediary vs Terminal operations in Streams
        // Streams are all lazily evaulated
        // until you call any terminal operation in the stream
        // the stream will not execute
        Stream<Employee> employeeStream = employees.stream();
        IntStream intStream = employeeStream.mapToInt(Employee::getAge);
        // If the stream has been converted to any primitive stream such as IntStream we cannot reuse the same stream again which we converted to IntStream
        Stream<Integer> integerStream = employees.stream().map(Employee::getAge);
//        System.out.println("Total size:"+integerStream.count());
        // There are some Primitive streams like IntStream, DoubleStream, LongStream that are used specifically to work on primitive types
        // The stream will never get executed until you call the Terminal operation
        // here sum is a terminal operation
        // Example of terminal operation
//        intStream.sum();

        // Collectors example

        // beforeCollectors
        List<String> namesList = new ArrayList<>();
        for (Employee emp : employees) {
            namesList.add(emp.getName());
        }

        // after collectors
        List<String> names = employees.stream().map(Employee::getName).collect(Collectors.toList());
        Set<String> withoutDuplicateNames = employees.stream().map(Employee::getName).collect(Collectors.toSet());
        System.out.println(withoutDuplicateNames);

        // Need to learn about Optional, need to understand the below example
        // Get me the first employee who's age is greater than 18
        Optional<Employee> employeeOptional = employees.stream().filter(e -> e.getAge() > 18).findFirst();

    }
}

class Employee {
    private String name;
    private int age;

    public Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

@FunctionalInterface
interface Shape {
    // single abstract method
    int sides(int num1, int num2);

    // By Java 8 we can use default and static methods in interface.
    default String version() {
        return "Using JDK 17";
    }

    static String customClassName() {
        return Shape.class.getName();
    }

}

class Printer {

    void print() {
        System.out.println("From printer");
    }
}

class Circle extends Printer implements Shape {
    @Override
    public int sides(int num1, int num2) {
        return 0;
    }

    @Override
    void print() {
        System.out.println("From circle way!!");
    }
}
vasanth0989 commented 9 months ago

Java 8:

Java8 Streams

Streams:

Examples of terminal operation

forEach: Performs an action for each element of the stream.

toArray: Collects the elements of the stream into an array.

reduce: Performs a reduction on the elements of the stream, resulting in a single value.

collect: Performs a mutable reduction operation on the elements of the stream, resulting in a collection.

min: Finds the minimum element of the stream according to a given comparator.

max: Finds the maximum element of the stream according to a given comparator.

count: Returns the count of elements in the stream as a long.

anyMatch: Checks if any element of the stream matches a given predicate.

allMatch: Checks if all elements of the stream match a given predicate.

noneMatch: Checks if none of the elements of the stream match a given predicate.

findFirst: Returns the first element of the stream wrapped in an Optional.

findAny: Returns any element of the stream wrapped in an Optional.
vasanth0989 commented 9 months ago

More Streams example using 'groupingBy' and 'joining' from 'Collectors'

import java.util.*;
import java.util.stream.Collectors;

public class TestMain {

    public static void main(String[] args) throws Exception {

     // Let's do more Streaming
        List<Account> accounts = new ArrayList<>();
        accounts.add(new Account(1, "CHK", Arrays.asList("A1", "A2")));
        accounts.add(new Account(2, "SVG", Arrays.asList("A3", "A4")));
        accounts.add(new Account(3, "CHK", Arrays.asList("A5", "A6")));
        accounts.add(new Account(4, "SVG", Arrays.asList("A7", "A8")));

        // Group the accounts by its Type
        // meaning Account type CHK should hold both Account id 1 and 3
        // Let's see how we do it before java 8
        Map<String, List<Account>> b4Java8Mp = new HashMap<>();
        for(Account account: accounts){
            String accountType = account.getType();
            if(!b4Java8Mp.containsKey(accountType)){
                List<Account> accts = new ArrayList<>();
                accts.add(account);
                b4Java8Mp.put(accountType, accts);
            }else{
                b4Java8Mp.get(accountType).add(account);
            }
        }

        System.out.println("Using Java8 Map"+b4Java8Mp);

        // Now Using Java8 Streams and Collectors we can do everything in single ine
        Map<String, List<Account>> java8Mp = accounts.stream().collect(Collectors.groupingBy(Account::getType));

        // Help me reduce the List of nick names to single string value, like A1,A2,A3..
        String nickNames = accounts.stream().flatMap(acct -> acct.getNickNames().stream()).collect(Collectors.joining(","));
        System.out.println("NickNames here:"+nickNames);

    }
}

class Account {

    private int id;
    private String type;
    private List<String> nickNames;

    public Account() {
    }

    public Account(int id, String type, List<String> nickNames) {
        this.id = id;
        this.type = type;
        this.nickNames = nickNames;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public List<String> getNickNames() {
        return nickNames;
    }

    public void setNickNames(List<String> nickNames) {
        this.nickNames = nickNames;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", type='" + type + '\'' +
                ", nickNames=" + nickNames +
                '}';
    }
}
vasanth0989 commented 9 months ago

ctrl+alt+l -> is for formatting the code alt+enter -> is to get import suggestion ctrl+alt+o -> to organize or remove unused imports