0% found this document useful (0 votes)
2 views

Java Unit 3 Part 3 (1)

The document provides an overview of various Java programming concepts including method references, the Stream API, Base64 encoding and decoding, the forEach loop, try-with-resources, and type and repeating annotations. It explains how to use these features with examples and highlights their benefits and functionalities. Key operations of the Stream API, such as intermediate and terminal operations, are also discussed along with practical coding examples.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Java Unit 3 Part 3 (1)

The document provides an overview of various Java programming concepts including method references, the Stream API, Base64 encoding and decoding, the forEach loop, try-with-resources, and type and repeating annotations. It explains how to use these features with examples and highlights their benefits and functionalities. Key operations of the Stream API, such as intermediate and terminal operations, are also discussed along with practical coding examples.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

lOMoARcPSD|38190532

sayable2.say();
}
}

Output:
Hello, this is non-static method.
Hello, this is non-static method.

3) Reference to a Constructor
You can refer a constructor by using the new keyword. Here, we are referring constructor
with the help of functional interface.

Syntax

ClassName::new

Example

interface Messageable{
Message getMessage(String msg);
}
class Message{
Message(String msg){
System.out.print(msg);
}
}
public class ConstructorReference {
public static void main(String[] args) {
Messageable hello = Message::new;
hello.getMessage("Hello");
}
}

Output:

Hello

4.Stream In Java
Introduced in Java 8, Stream API is used to process collections of objects. A stream in Java is
a sequence of objects that supports various methods which can be pipelined to produce the
desired result.

Use of Stream in Java


There uses of Stream in Java are mentioned below:

Stream API is a way to express and process collections of objects.


Enable us to perform operations like filtering, mapping,reducing and sorting.
How to Create Java Stream?
Java Stream Creation is one of the most basic steps before considering the functionalities of
the Java Stream. Below is the syntax given on how to declare Java Stream.

Syntax
lOMoARcPSD|38190532

Stream<T> stream;
Here T is either a class, object, or data type depending upon the declaration.

Java Stream Features


The features of Java stream are mentioned below:

A stream is not a data structure instead it takes input from the Collections, Arrays or I/O
channels.
Streams don’t change the original data structure, they only provide the result as per the
pipelined methods.
Each intermediate operation is lazily executed and returns a stream as a result, hence various
intermediate operations can be pipelined. Terminal operations mark the end of the stream and
return the result.
Different Operations On Streams
There are two types of Operations in Streams:
Intermediate Operations
Terminate Operations

Intermediate Operations

Intermediate Operations are the types of operations in which multiple methods are
chained in a row.

Characteristics of Intermediate Operations


Methods are chained together.
Intermediate operations transform a stream into another stream.
It enables the concept of filtering where one method filters data and passes it to another
method after processing.
Benefit of Java Stream
There are some benefits because of which we use Stream in Java as mentioned below:

No Storage
Pipeline of Functions
Laziness
Can be infinite
Can be parallelized
Can be created from collections, arrays, Files Lines, Methods in Stream, IntStream etc.

Important Intermediate Operations


There are a few Intermediate Operations mentioned below:
lOMoARcPSD|38190532

1. map()
The map method is used to return a stream consisting of the results of applying the given
function to the elements of this stream.

List number = Arrays.asList(2,3,4,5);


List square = number.stream().map(x->x*x).collect(Collectors.toList());
2. filter()
The filter method is used to select elements as per the Predicate passed as an argument.

List names = Arrays.asList("Reflection","Collection","Stream");


List result = names.stream().filter(s->s.startsWith("S")).collect(Collectors.toList());
3. sorted()
The sorted method is used to sort the stream.

List names = Arrays.asList("Reflection","Collection","Stream");


List result = names.stream().sorted().collect(Collectors.toList());
Terminal Operations
Terminal Operations are the type of Operations that return the result. These Operations are
not processed further just return a final result value.

Important Terminal Operations


There are a few Terminal Operations mentioned below:

1. collect()
The collect method is used to return the result of the intermediate operations performed on
the stream.

List number = Arrays.asList(2,3,4,5,3);


Set square = number.stream().map(x->x*x).collect(Collectors.toSet());
2. forEach()
The forEach method is used to iterate through every element of the stream.

List number = Arrays.asList(2,3,4,5);


number.stream().map(x->x*x).forEach(y->System.out.println(y));
3. reduce()
The reduce method is used to reduce the elements of a stream to a single value. The reduce
method takes a BinaryOperator as a parameter.

List number = Arrays.asList(2,3,4,5);


int even = number.stream().filter(x->x%2==0).reduce(0,(ans,i)-> ans+i);
Here ans variable is assigned 0 as the initial value and i is added to it.

Note: Intermediate Operations are running based on the concept of Lazy Evaluation, which
ensures that every method returns a fixed value(Terminal operation) before moving to the
next method.

Example of Java Stream


Java

// Java program to demonstrate


// the use of stream in java
import java.util.*;
import java.util.stream.*;
lOMoARcPSD|38190532

class Demo {
public static void main(String args[])
{
// create a list of integers
List<Integer> number = Arrays.asList(2, 3, 4, 5);

// demonstration of map method


List<Integer> square
= number.stream()
.map(x -> x * x)
.collect(Collectors.toList());

// create a list of String


List<String> names = Arrays.asList(
"Reflection", "Collection", "Stream");

// demonstration of filter method


List<String> result
= names.stream()
.filter(s -> s.startsWith("S"))
.collect(Collectors.toList());

System.out.println(result);

// demonstration of sorted method


List<String> show
= names.stream()
.sorted()
.collect(Collectors.toList());

System.out.println(show);

// create a list of integers


List<Integer> numbers
= Arrays.asList(2, 3, 4, 5, 2);

// collect method returns a set


Set<Integer> squareSet
= numbers.stream()
.map(x -> x * x)
.collect(Collectors.toSet());

System.out.println(squareSet);

// demonstration of forEach method


number.stream()
.map(x -> x * x)
.forEach(y -> System.out.println(y));

// demonstration of reduce method


int even
= number.stream()
.filter(x -> x % 2 == 0)
lOMoARcPSD|38190532

.reduce(0, (ans, i) -> ans + i);

System.out.println(even);
}
}
Output

[4, 9, 16, 25]


[Stream]
[Collection, Reflection, Stream]
[16, 4, 9, 25]
4
9
16
25
6

5. Basic Type Base64 Encoding and Decoding in Java

In computer programming, Base64 is a group of binary-to-text encoding schemes that


transforms binary data into a sequence of printable characters, limited to a set of 64 unique
characters. More specifically, the source binary data is taken 6 bits at a time, then this group of
6 bits is mapped to one of 64 unique characters.
As with all binary-to-text encoding schemes, Base64 is designed to carry data stored in binary
formats across channels that only reliably support text content. Base64 is particularly prevalent
on the World Wide Web[1] where one of its uses is the ability to embed image files or other
binary assets inside textual assets such as HTML and CSS files.[2]
Base64 is also widely used for sending e-mail attachments, because SMTP – in its original
form – was designed to transport 7-bit ASCII characters only. Encoding an attachment as
Base64 before sending, and then decoding when received, assures older SMTP servers will not
interfere with the attachment.

Base 64 is an encoding scheme that converts binary data into text format so that encoded
textual data can be easily transported over network un-corrupted and without any data
loss.(Base 64 format reference).
The Basic encoding means no line feeds are added to the output and the output is mapped to a
set of characters in A-Za-z0-9+/ character set and the decoder rejects any character outside of
this set.

Encode simple String into Basic Base 64 format

String BasicBase64format= Base64.getEncoder().encodeToString(“actualString”.getBytes());

Explanation: In above code we called Base64.Encoder using getEncoder() and then get the
encoded string by passing the byte value of actualString in encodeToString() method as
parameter.

Decode Basic Base 64 format to String

byte[] actualByte= Base64.getDecoder().decode(encodedString);


String actualString= new String(actualByte);
lOMoARcPSD|38190532

Explanation: In above code we called Base64.Decoder using getDecoder() and then decoded
the string passed in decode() method as parameter then convert return value to string.

Below programs illustrate the Encoding and Decoding in Java:

Program 1:Encode simple String into Basic Base 64 format


// Java program to demonstrate
// Encoding simple String into Basic Base 64 format

import java.util.*;
public class GFG {
public static void main(String[] args)
{

// create a sample String to encode


String sample = "India Team will win the Cup";

// print actual String


System.out.println("Sample String:\n" + sample);

// Encode into Base64 format


String BasicBase64format = Base64.getEncoder().encodeToString(sample.getBytes());

// print encoded String


System.out.println("Encoded String:\n" + BasicBase64format);
}
}
Output:
Sample String: India Team will win the Cup
Encoded String: SW5kaWEgVGVhbSB3aWxsIHdpbiB0aGUgQ3Vw

Program 2: Decode Basic Base 64 format to String


// Java program to demonstrate
// Decoding Basic Base 64 format to String

import java.util.*;
public class GFG {
public static void main(String[] args)
{
// create an encoded String to decode
String encode = "SW5kaWEgVGVhbSB3aWxsIHdpbiB0aGUgQ3Vw";
// print encoded String
System.out.println("Encoded String:\n+ encoded);
// decode into String from encoded format
byte[] actualByte = Base64.getDecoder() .decode(encoded);

String actualString = new String(actualByte);


// print actual String
System.out.println("actual String:\n"
+ actualString);
}
}
Output:
lOMoARcPSD|38190532

Encoded String: SW5kaWEgVGVhbSB3aWxsIHdpbiB0aGUgQ3Vw


actual String: India Team will win the Cup

6. Java forEach loop

Java provides a new method forEach() to iterate the elements. It is defined in Iterable and
Stream interface. It is a default method defined in the Iterable interface. Collection classes
which extends Iterable interface can use forEach loop to iterate elements.
This method takes a single parameter which is a functional interface. So, you can pass
lambda expression as an argument.

forEach() Signature in Iterable Interface


default void forEach(Consumer<super T>action)

Java 8 forEach() example 1

import java.util.ArrayList;
import java.util.List;
public class ForEachExample {
public static void main(String[] args) {
List<String> gamesList = new ArrayList<String>();
gamesList.add("Football");
gamesList.add("Cricket");
gamesList.add("Chess");
gamesList.add("Hocky");
System.out.println("------------Iterating by passing lambda expression--------------");
gamesList.forEach(games -> System.out.println(games));
} }
Output:
------------Iterating by passing lambda expression--------------
Football Cricket Chess Hocky

Java 8 forEach() example 2

import java.util.ArrayList;
import java.util.List;
public class ForEachExample {
public static void main(String[] args) {
List<String> gamesList = new ArrayList<String>();
gamesList.add("Football");
gamesList.add("Cricket");
gamesList.add("Chess");
gamesList.add("Hocky");
System.out.println("------------Iterating by passing method reference---------------");
gamesList.forEach(System.out::println);
} }
Output:
------------Iterating by passing method reference---------------
Football Cricket Chess Hocky

7.Try-with-resources Feature in Java


lOMoARcPSD|38190532

In Java, the Try-with-resources statement is a try statement that declares one or more
resources in it. A resource is an object that must be closed once your program is done using
it. For example, a File resource or a Socket connection resource. The try-with-resources
statement ensures that each resource is closed at the end of the statement execution. If we
don’t close the resources, it may constitute a resource leak and also the program could
exhaust the resources available to it.

You can pass any object as a resource that implements java.lang.AutoCloseable, which
includes all objects which implement java.io.Closeable.

By this, now we don’t need to add an extra finally block for just passing the closing
statements of the resources. The resources will be closed as soon as the try-catch block is
executed.

Syntax: Try-with-resources

try(declare resources here) {


// use resources
}
catch(FileNotFoundException e) {
// exception handling
}

Exceptions:

When it comes to exceptions, there is a difference in try-catch-finally block and try-with-


resources block. If an exception is thrown in both try block and finally block, the method
returns the exception thrown in finally block.
For try-with-resources, if an exception is thrown in a try block and in a try-with-resources
statement, then the method returns the exception thrown in the try block. The exceptions
thrown by try-with-resources are suppressed, i.e. we can say that try-with-resources block
throws suppressed exceptions.

Now, let us discuss both the possible scenarios which are demonstrated below as an example
as follows:
Case 1: Single resource
Case 2: Multiple resources

Example 1: try-with-resources having a single resource

// Java Program for try-with-resources


// having single resource

// Importing all input output classes


import java.io.*;

// Class
class GFG {

// Main driver method


public static void main(String[] args)
{
// Try block to check for exceptions
lOMoARcPSD|38190532

try (

// Creating an object of FileOutputStream


// to write stream or raw data

// Adding resource
FileOutputStream fos = new FileOutputStream("gfgtextfile.txt")) {

// Custom string input


String text = "Hello World. This is my java program";

// Converting string to bytes


byte arr[] = text.getBytes();

// Text written in the file


fos.write(arr);
}

// Catch block to handle exceptions


catch (Exception e) {

// Display message for the occurred exception


System.out.println(e);
}

// Display message for successful execution of


// program
System.out.println(
"Resource are closed and message has been written into the gfgtextfile.txt");
}
}
Output:

Resource are closed and message has been written into the gfgtextfile.txt

8.Java Type and Repeating Annotations

Java Type Annotations


Java 8 has included two new features repeating and type annotations in its prior annotations
topic. In early Java versions, you can apply annotations only to declarations. After releasing
of Java SE 8 , annotations can be applied to any type use. It means that annotations can be
lOMoARcPSD|38190532

used anywhere you use a type. For example, if you want to avoid NullPointerException in
your code, you can declare a string variable like this:

@NonNull String str;


Following are the examples of type annotations:

@NonNull List<String>
List<@NonNull String> str
Arrays<@NonNegative Integer> sort
@Encrypted File file
@Open Connection connection
void divideInteger(int a, int b) throws @ZeroDivisor ArithmeticException
Note - Java created type annotations to support improved analysis of Java programs. It
supports way of ensuring stronger type checking.

Java Repeating Annotations


In Java 8 release, Java allows you to repeating annotations in your source code. It is helpful
when you want to reuse annotation for the same class. You can repeat an annotation anywhere
that you would use a standard annotation.

For compatibility reasons, repeating annotations are stored in a container annotation that is
automatically generated by the Java compiler. In order for the compiler to do this, two
declarations are required in your code.
1. Declare a repeatable annotation type
2. Declare the containing annotation type

1) Declare a repeatable annotation type


Declaring of repeatable annotation type must be marked with the @Repeatable meta-
annotation. In the following example, we have defined a custom @Game repeatable
annotation type.

@Repeatable(Games.class)
@interfaceGame{
String name();
String day();
}
The value of the @Repeatable meta-annotation, in parentheses, is the type of the container
annotation that the Java compiler generates to store repeating annotations. In the following
example, the containing annotation type is Games. So, repeating @Game annotations is
stored in an @Games annotation.

2) Declare the containing annotation type


Containing annotation type must have a value element with an array type. The component
type of the array type must be the repeatable annotation type. In the following example, we
are declaring Games containing annotation type:

@interfaceGames{
Game[] value();
}
Note - Compiler will throw a compile-time error, if you apply the same annotation to a
declaration without first declaring it as repeatable.

Java Repeating Annotations Example


lOMoARcPSD|38190532

// Importing required packages for repeating annotation

import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
// Declaring repeatable annotation type
@Repeatable(Games.class)
@interfaceGame{
String name();
String day();
}
// Declaring container for repeatable annotation type
@Retention(RetentionPolicy.RUNTIME)
@interfaceGames{
Game[] value();
}
// Repeating annotation
@Game(name = "Cricket", day = "Sunday")
@Game(name = "Hockey", day = "Friday")
@Game(name = "Football", day = "Saturday")
public class RepeatingAnnotationsExample {
public static void main(String[] args) {
// Getting annotation by type into an array
Game[] game =
RepeatingAnnotationsExample.class.getAnnotationsByType(Game.class);
for (Gamegame2 : game) { // Iterating values
System.out.println(game2.name()+" on "+game2.day());
}
}
}
OUTPUT:

Cricket on Sunday
Hockey on Friday
Football on Saturday

9.Java 9 Module System

Java Module System is a major change in Java 9 version. Java added this feature to collect
Java packages and code into a single unit called module.

In earlier versions of Java, there was no concept of module to create modular Java
applications, that why size of application increased and difficult to move around. Even JDK
itself was too heavy in size, in Java 8, rt.jar file size is around 64MB.

To deal with situation, Java 9 restructured JDK into set of modules so that we can use only
required module for our project.

Apart from JDK, Java also allows us to create our own modules so that we can develop
module based application.
The module system includes various tools and options that are given below.

You might also like