Java 8

Q: What are the new features of java 8 ?

Ans:

1. Stream API:
Question: Write a Java 8 function that takes a list of integers and returns a list of even integers sorted in descending order.
Follow-Up: How would you modify the function to return only the first 3 even integers?
Example Solution:

import java.util.List;
import java.util.stream.Collectors;

public class Example {
    public List<Integer> getEvenNumbersDescending(List<Integer> numbers) {
        return numbers.stream()
                      .filter(n -> n % 2 == 0)
                      .sorted((a, b) -> b - a)  // Sorting in descending order
                      .collect(Collectors.toList());
    }
    
    public List<Integer> getFirstThreeEvenNumbersDescending(List<Integer> numbers) {
        return numbers.stream()
                      .filter(n -> n % 2 == 0)
                      .sorted((a, b) -> b - a)  // Sorting in descending order
                      .limit(3)                 // Limiting to the first 3 results
                      .collect(Collectors.toList());
    }
}

2. Functional Interfaces:
Question: Create a custom functional interface that takes two integers and returns their sum. Then, use it in a lambda expression.
Example Solution:

@FunctionalInterface
interface Adder {
    int add(int a, int b);
}

public class Example {
    public static void main(String[] args) {
        Adder adder = (a, b) -> a + b;
        System.out.println("Sum: " + adder.add(5, 3));  // Output: Sum: 8
    }
}

3. Optional:
Question: Write a method that finds the first string in a list that starts with the letter "A". If no such string is found, return "Not found" using Optional.
Example Solution:

import java.util.List;
import java.util.Optional;

public class Example {
    public String findFirstStringStartingWithA(List<String> strings) {
        return strings.stream()
                      .filter(s -> s.startsWith("A"))
                      .findFirst()
                      .orElse("Not found");
    }
}

4. Map and Reduce:
Question: Given a list of integers, write a method to find the product of all integers using Java 8 streams.
Example Solution:

import java.util.List;

public class Example {
    public int findProduct(List<Integer> numbers) {
        return numbers.stream()
                      .reduce(1, (a, b) -> a * b);  // Multiply all elements
    }
}

5. Default and Static Methods in Interfaces:
Question: Create an interface with a default method that returns a greeting message. Then, implement this interface in a class and demonstrate the usage of the default method.
Example Solution:

interface Greeter {
    default String greet() {
        return "Hello!";
    }
}

public class Example implements Greeter {
    public static void main(String[] args) {
        Example example = new Example();
        System.out.println(example.greet());  // Output: Hello!
    }
}

6. Lambda Expressions and Method References:
Question: Given a list of strings, write a method that converts all strings to uppercase using method references.
Example Solution:

import java.util.List;
import java.util.stream.Collectors;

public class Example {
    public List<String> convertToUpper(List<String> strings) {
        return strings.stream()
                      .map(String::toUpperCase)  // Using method reference
                      .collect(Collectors.toList());
    }
}

7. Parallel Streams:
Question: What are parallel streams, and how would you use them to find the sum of a large list of integers?
Example Answer: Parallel streams are a feature in Java 8 that allow you to process data in parallel, potentially improving performance on large datasets by utilizing multiple CPU cores. However, they should be used carefully due to possible thread-safety issues.

Example Solution:

import java.util.List;

public class Example {
    public int sumWithParallelStream(List<Integer> numbers) {
        return numbers.parallelStream()
                      .mapToInt(Integer::intValue)
                      .sum();
    }
}

8. Collectors Grouping:
Question: Write a method that groups a list of strings by their length using Collectors.groupingBy().
Example Solution:

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Example {
    public Map<Integer, List<String>> groupByLength(List<String> strings) {
        return strings.stream()
                      .collect(Collectors.groupingBy(String::length));
    }
}

 Q :What distinguishes a collection from a stream?

Ans; A Collection contains its elements, whereas a Stream does not, and this is the primary distinction between the two types of data structures. Unlike other views, Stream operates on a view whose elements are kept in a collection or array, but any changes made to Stream do not affect the original collection.

 

Q: What is the function map() used for? You use it, why?

Ans: In Java, functional map operations are performed using the map() function. This indicates that it can apply a function to change one type of object into another.

Use map(), for instance, to change a List of String into a List of Integers if you have one already.

It will apply to all elements of the List and give you a List of Integer if you only supply a function to convert String to Integer, such as parseInt() or map(). The map can change one object into another.


Q :What distinguishes a Java functional interface from a conventional interface?

Ans: While the functional interface in Java can only contain one abstract method, the normal interface can contain any number of abstract methods.

They wrap a function in an interface, which is why they are termed functional interfaces. The one abstract method on the interface serves as the function's representation.


Q: Print odd/even numbers from Array and List with java Stream

Ans:

public static void main(String[] args) 
    {
        List<Integer> numbers = Arrays.asList(1, 4, 8, 40, 11, 22, 33, 99);

       List<Integer> oddNumbers = numbers.stream().filter(o -> o % 2 != 0).collect(Collectors.toList());

        List<Integer> evenNumbers = numbers.stream().filter(o -> o % 2 = 0).collect(Collectors.toList());

        System.out.println(oddNumbers);

        System.out.println(evenNumbers);

    }


Q: How to use stream in Map ?

Ans:
Stream of Keys
If you're only interested in the keys, you can create a stream from the keySet() of the Map.

map.keySet().stream().forEach(key -> System.out.println("Key: " + key));
Stream of Values
Similarly, you can create a stream from the values() of the Map if you're only interested in the values.

map.values().stream().forEach(value -> System.out.println("Value: " + value));


Q: Print odd/even numbers from a Set with java Stream

Ans:
    public static void main(String[] args) 
    {
        Set<Integer> oddNumbers = numbers.stream().filter(o -> o % 2 != 0).collect(Collectors.toSet());
        System.out.println(oddNumbers);
    }

Q: What does the Java 8 StringJoiner Class mean? How can we use the StringJoiner Class to join several Strings?

StringJoiner is a new class that was added to the java.util package in Java 8. With the help of this class, we may combine numerous strings that have been separated by delimiters and add prefixes and suffixes to them.

Using the StringJoiner Class, we will learn how to join several Strings in the program below. The delimiter between the two strings in this instance is ",". After that, we combined five distinct strings by adding them together using the add() method. The String Joiner was then printed.

import java.util.StringJoiner;
 public class Java8 {
    public static void main(String[] args) {
 
        StringJoiner stj = new StringJoiner(",");
        // Separated the elements with a comma in between.
         
        stj.add("Saket");
        stj.add("John");
        stj.add("Franklin");
        stj.add("Ricky");
        stj.add("Trevor");
         
        // Added elements into StringJoiner “stj”
         
        System.out.println(stj);
    }
}


Q : How does a lambda expression relate to a functional interface? What is a lambda expression in Java?

A function type without a name is a lambda expression. Results and parameters may or may not be present. Since it lacks type information, it is referred to as an anonymous function. It is carried out as needed. It helps with data extraction, filtering, and iteration from collections.

Lambda expressions can only be used with the single abstract method of the Functional Interface since they are equivalent to anonymous functions. From the signature of the abstract method of the functional interface, it will deduce the return type, type, and several parameters.

Q: Write some sample program to use stream functions

Ans:

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

import static jdk.nashorn.internal.objects.NativeArray.forEach;

public class Java8Demo {

    @Test
    public void removespecialchar() {

        String str = "t.,/r}-y";
        str = str.replaceAll("[^a-zA-Z0-9]", "");
        System.out.println(str);
    }

    @Test
    public void oddeven() {

        List<Integer> numbers = Arrays.asList(1, 4, 8, 40, 11, 22, 33, 99);

        List<Integer> evennumbers =numbers.stream().filter(n->n%2==0).collect(Collectors.toList());
        numbers.stream().filter(n->n%2==0).forEach(System.out::println);
        System.out.println(evennumbers);
    }

    @Test
    public void flatmap() {

        // Creating a List of Lists
        List<List<String>> listOfLists = Arrays.asList(
                Arrays.asList("A", "B"),
                Arrays.asList("C", "D"),
                Arrays.asList("E", "F")
        );

        // Using Stream flatMap(Function mapper)
        listOfLists.stream().flatMap(list -> list.stream()).forEach(System.out::println);
    }

    @Test
    public void flatmap2()
    {
        // Creating a List of Strings
        List<String> list = Arrays.asList("Geeks", "GFG", "GeeksforGeeks", "gfg");

        // Using Stream flatMap(Function mapper)
        list.stream().flatMap(str -> Stream.of(str.charAt(2))).forEach(System.out::println);
    }

    @Test
    public void charcount()
    {
        // Creating a List of Strings
        List<String> list = Arrays.asList("A", "A", "C", "D","E","D");

        // Using distinct function
        list.stream().distinct().forEach(System.out::println);
        list.stream().limit(3).forEach(System.out::print);
       long num =  list.stream().filter(n->n.startsWith("A")).count();
       System.out.println(" "+num);
    }

    @Test
    public void minmax()
    {
        // Creating a List of Integer
        List<Integer> list = Arrays.asList(2,3,9,3,1,5);

        // Using min function
       Optional<Integer> min = list.stream().min( (a1, a2)->{ return a1.compareTo(a2); } );
       System.out.println(min.get());

    }
    @Test
    public void max()
    {
        // Creating a List of Integer
        List<Integer> list = Arrays.asList(2,3,9,3,1,5);

        // Using min function
        Object[] a = list.stream().toArray();
        System.out.println(a.length);
        for(Object b :a)
            System.out.println(b);

    }

    @Test
    public void sorting()
    {
        // Creating a List of Integer
        List<Integer> list = Arrays.asList(2,3,9,1,1,3,1,5);

        // Using sorted
        List<Integer> a = list.stream().sorted().collect(Collectors.toList());
        System.out.println(a);

        List<Integer> b = list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
        System.out.println(b);

    }
}


Q: A Stream API: What Is It? Why is the Stream API necessary?

Ans:
Java 8 now has a new functionality called Stream API. Stream API is a unique class used for handling items from sources like collections.

The Stream API is required because: 
  • Processing is straightforward since it offers aggregate operations.
  • Programming in the functional style is supported.
  • The processing speed is accelerated. It is, therefore, suitable for greater performance.
  • Parallel operations are possible.

Q: Can you convert an array to Stream? How? 

Ans:
Yes, you can convert an array to Stream in Java. The Stream class provides a factory method to create a Stream from an array, like Stream .of(T ...) which 
accepts a variable argument, that means you can also pass an array to it as shown in the following example:

String[] languages = {"Java", "Python", "JavaScript"};
Stream numbers = Stream.of(languages);
numbers.forEach(System.out::println);

Output:
Java
Python
JavaScript

Q: Operation on map with stream API 

Ans:

        Map<String, Integer> map = new HashMap<>();
        map.put("Alice", 30);
        map.put("Bob", 25);
        map.put("Charlie", 35);

        // Iterate over the Map using Stream API
        map.entrySet().stream().forEach(entry -> System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue()));
==========================================================================

        Map<String, Integer> map = new HashMap<>();
        map.put("Alice", 30);
        map.put("Bob", 25);
        map.put("Charlie", 35);

        // Filter and transform entries using Streams
        Map<String, Integer> filteredMap = map.entrySet().stream()
            .filter(entry -> entry.getValue() >= 30)  // Filter entries
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); // Collect to new Map

        // Print the filtered Map
        filteredMap.forEach((key, value) -> 
            System.out.println("Key: " + key + ", Value: " + value)
        );
===========================================================================

        Map<String, Integer> map = new HashMap<>();
        map.put("Alice", 30);
        map.put("Bob", 25);
        map.put("Charlie", 35);

        // Iterate over keys using Stream API
        map.keySet().stream()
            .forEach(key -> 
                System.out.println("Key: " + key)
            );
===========================================================================
        Map<String, Integer> map = new HashMap<>();
        map.put("Alice", 30);
        map.put("Bob", 25);
        map.put("Charlie", 35);

        // Iterate over values using Stream API
        map.values().stream()
            .forEach(value -> 
                System.out.println("Value: " + value)
            );
============================================================================

Q: What are the build-in functions present in Stream API ?

Ans:
1. filter()
Purpose: Filters elements of the stream based on a given predicate.
Lambda Expression Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> evenNumbers = numbers.stream()
                                   .filter(n -> n % 2 == 0)
                                   .collect(Collectors.toList());
// Output: [2, 4, 6]

2. map()
Purpose: Applies a function to each element and returns a stream of the results.
Lambda Expression Example:

List<String> names = Arrays.asList("John", "Jane", "Jack");
List<Integer> nameLengths = names.stream()
                                 .map(name -> name.length())
                                 .collect(Collectors.toList());
// Output: [4, 4, 4]

3. flatMap()
Purpose: Flattens a stream of collections into a single stream.
Lambda Expression Example:

List<List<String>> names = Arrays.asList(
    Arrays.asList("John", "Jane"),
    Arrays.asList("Jack", "Jill")
);
List<String> flatList = names.stream()
                             .flatMap(list -> list.stream())
                             .collect(Collectors.toList());
// Output: [John, Jane, Jack, Jill]

4. reduce()
Purpose: Reduces the elements of a stream to a single value.
Lambda Expression Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
int sum = numbers.stream()
                 .reduce(0, (a, b) -> a + b);
// Output: 10

5. collect()
Purpose: Collects the elements of a stream into a collection.
Lambda Expression Example:
java
Copy code
List<String> names = Arrays.asList("John", "Jane", "Jack");
List<String> uppercaseNames = names.stream()
                                   .map(name -> name.toUpperCase())
                                   .collect(Collectors.toList());
// Output: [JOHN, JANE, JACK]

6. forEach()
Purpose: Performs an action for each element of the stream.
Lambda Expression Example:
java
Copy code
List<String> names = Arrays.asList("John", "Jane", "Jack");
names.stream().forEach(name -> System.out.println(name));
// Output: John, Jane, Jack

7. sorted()
Purpose: Sorts the elements of the stream.
Lambda Expression Example:

List<String> names = Arrays.asList("John", "Jane", "Jack");
List<String> sortedNames = names.stream()
                                .sorted((a, b) -> a.compareTo(b))
                                .collect(Collectors.toList());
// Output: [Jack, Jane, John]

8. distinct()
Purpose: Removes duplicate elements from the stream.
Lambda Expression Example:
java
Copy code
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5);
List<Integer> distinctNumbers = numbers.stream()
                                       .distinct()
                                       .collect(Collectors.toList());
// Output: [1, 2, 3, 4, 5]

9. limit()
Purpose: Limits the number of elements in the stream.
Lambda Expression Example:
java
Copy code
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> limitedNumbers = numbers.stream()
                                      .limit(3)
                                      .collect(Collectors.toList());
// Output: [1, 2, 3]

10. skip()
Purpose: Skips a certain number of elements in the stream.
Lambda Expression Example:
java
Copy code
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> skippedNumbers = numbers.stream()
                                      .skip(2)
                                      .collect(Collectors.toList());
// Output: [3, 4, 5]

11. anyMatch(), allMatch(), noneMatch()
Purpose: Checks if any, all, or none of the elements match a given predicate.
Lambda Expression Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean hasEven = numbers.stream().anyMatch(n -> n % 2 == 0); // true
boolean allEven = numbers.stream().allMatch(n -> n % 2 == 0); // false
boolean noneNegative = numbers.stream().noneMatch(n -> n < 0); // true

12. findFirst() and findAny()
Purpose: Finds the first or any element in the stream.
Lambda Expression Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> first = numbers.stream().findFirst(); // Output: Optional[1]
Optional<Integer> any = numbers.stream().findAny();     // Output: Optional[1] or any other element


Q: Write a program to print prime number with java stream

Ans:

 public static void main(String[] args) {
        int number = 6; // Replace with the number you want to check
        boolean isPrime = isPrime(number);
        System.out.println(number + " is prime: " + isPrime);
    }

    public static boolean isPrime(int number) {
        // Edge cases
        if (number <= 1) return false;
        if (number == 2) return true; // 2 is the only even prime number
        if (number % 2 == 0) return false; // Eliminate even numbers greater than 2

        // Check divisibility from 3 to sqrt(number) using stream
        return IntStream.rangeClosed(3, (int) Math.sqrt(number))
                        .filter(i -> i % 2 != 0) // Only check odd numbers
                        .noneMatch(i -> number % i == 0);
    }
  • We use IntStream.rangeClosed to create a stream of integers from 3 up to the square root of the number. This is because a larger factor of the number must be paired with a smaller factor that would have already been checked.
  • We filter out even numbers since we’ve already handled divisibility by 2.
  • We use noneMatch to check if there is any number in the range that divides the given number without a remainder. If there is no such number, the number is prime.

        List<String> names = Arrays.asList("John", "Jane", "Doe", "Doe");
        names.forEach(System.out::println);
        System.out.println("=================");
        
        names.stream().map(n->n.toUpperCase()).forEach(System.out::println);
        System.out.println("=================");
        
        Set<String> setname = new HashSet<String>(names);
        setname.forEach(System.out::println);
        System.out.println("=================");
        
        Set<String> setname1 =names.stream().map(n->n.toUpperCase()).collect(Collectors.toSet());
        setname1.forEach(System.out::println);
         System.out.println("=================");
         
        names.stream().filter(n->n.startsWith("J")).forEach(System.out::println); 
        
         System.out.println("=================");
         
        names.stream().filter(n->n.length()>2).forEach(System.out::println);
        
        System.out.println("=================");
         
        names.stream().filter(n->n.length()>2).forEach(System.out::println);
        
    }

Comments