Java 9-16 all useful features
Java 9
Private methods inside interface
package com.java.demo;
interface StringManipulationUtil{
private static String reverseString(String str){
return new StringBuilder(str).reverse().toString();
}
static String toUpperReverse(String str){
String upperStr = str.toUpperCase();
return reverseString(upperStr);
}
static String toLowerReverse(String str){
String lowerStr = str.toLowerCase();
return reverseString(lowerStr);
}
}
public class Java9Demo {
public static void main(String[] args) {
System.out.println(StringManipulationUtil.toLowerReverse("Hello Java!!!"));
System.out.println(StringManipulationUtil.toUpperReverse("Hello Java!!!"));
}
}
takeWhile and dropWhile
List<Integer> integerList = Arrays.asList(1,2,3,4,5,6,7,8,9);
System.out.println("---takeWhile---");
integerList.stream()
.takeWhile(e->e<5)
.forEach(System.out::println);
System.out.println("---dropWhile---");
integerList.stream()
.dropWhile(e->e<5)
.forEach(System.out::println);
Closed Range
package com.company;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
IntStream.range(1,5).forEach(System.out::println);
System.out.println("--Closed Range--");
IntStream.rangeClosed(1,5).forEach(System.out::println);
}
}
More control over stream iterator
package com.company;
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
for (int i=0;i<=10;i+=2){
System.out.println(i);
}
System.out.println("-------");
IntStream
.iterate(0, i->i<=10, i->i+2)
.forEach(System.out::println);
}
}
ifPresentOrElse
package com.company;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> integerList = Arrays.asList(1,2,3,4,5,6,7,8);
integerList
.stream()
.filter(e->e>7).findFirst()
.ifPresentOrElse(System.out::println,
()-> System.out.println("Value doesn't exist"));
}
}
Or With Optional
List<Integer> integerList = Arrays.asList(1,2,3,4,5,6,7,8);
integerList
.stream()
.filter(e->e>10).findFirst()
.or(()-> Optional.of(-1)).ifPresentOrElse(System.out::println,
()->System.out.println("Value doesn't exists"));
Convert Optional into Stream
List<Integer> integerList = Arrays.asList(1,2,3,4,5,6,7,8);
integerList
.stream()
.filter(e->e>7).findFirst().stream()
// this is Java 16 method we will discuss it later
.mapMulti((number,consumer)-> IntStream.rangeClosed(1,10)
.forEach(e->consumer.accept(e*number)))
.forEach(System.out::println);
The of method
package com.company;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Main {
public static void main(String[] args) {
System.out.println(List.of(1,2,3,4,5,7,8,9));
System.out.println(Set.of(1,2,3,4,5,6));
System.out.println(Map.of(1,"One",2,"two",3,"three"));
}
}
class Resource implements AutoCloseable{
public Resource(){
System.out.println("created");
}
public void display(){
System.out.println("Resource");
}
public void close(){
System.out.println("Clean up");
}
}
class Resource2 implements AutoCloseable{
public Resource2(){
System.out.println("created2");
}
public void display(){
System.out.println("Resource2");
}
public void close(){
System.out.println("Clean up2");
}
}
public class Java9Demo {
public static void main(String[] args) {
Resource resource= new Resource();
Resource2 resource2= new Resource2();
try(resource;resource2){
resource.display();
resource2.display();
}
}
}
AutoCloseable Enhancements
Jshell
Jshell is REPL for Java :
- Read
- Event
- Loop
Enter in jshell using the command below
jshell
Create a String
jshell> "hello world"
$1 ==> "hello world"
Print the String
System.out.println($1)
Change the value it holds
$1= $1 + " again"
Adding 2 numbers
int sum = 1+2;
Conditional Statement
jshell> if(sum>0)
...> System.out.println("Positive")
Positive
Create Method
int negativeNumber(int n)
...> {
...> return -n;
...> }
| created method negativeNumber(int)
Call the created method
negativeNumber(sum)
Create Method before defining variable (Forward Refrencing)
jshell> int addRandomNumber(int n)
...> {
...> return n + RANDOM_NUMBER;
...> }
| created method addRandomNumber(int), however, it cannot be invoked until variable RANDOM_NUMBER is declared
Attempting to use the previous method
jshell> addRandomNumber(10)
| attempted to call method addRandomNumber(int) which cannot be invoked until variable RANDOM_NUMBER is declared
Defining the undefined variable
jshell> int RANDOM_NUMBER = 12;
RANDOM_NUMBER ==> 12
Calling after variable Definition
jshell> addRandomNumber(10)
$14 ==> 22
Creating a class in jshell
jshell> class Dummmy{
...> int number =3;
...> public void setNumber(int number){this.number=number; }
...> public int getNumber(){return number;}
...> }
created class Dummmy
jshell> Dummmy d = new Dummmy();
d ==> Dummmy@184f6be2
jshell> d.setNumber(
setNumber(
jshell> d.setNumber(3);
jshell> d.getNumber();
$18 ==> 3
Sleep in jshell
jshell> Thread.sleep(2000); System.out.println("Hello");
Hello
JShell Automatically Catches the Exception
jshell> 1/0
| java.lang.ArithmeticException thrown: / by zero
| at (#25:1)
Exit Jshell Console
jshell> /exit
Goodbye
/list lists all valid statements
jshell> /list
1 : "hello world"
2 : System.out.println($1)
3 : $1+ " again"
4 : $1= $1 + " again"
5 : int sum = 1+2;
6 : if(sum>0)
System.out.println("Positive");
7 : System.out.println("Positive");
8 : if(sum>0)
System.out.println("Positive");
9 : int negativeNumber(int n)
{
return -n;
}
10 : negativeNumber(sum)
11 : int addRandomNumber(int n)
{
return n + RANDOM_NUMBER;
}
12 : addRandomNumber(10)
13 : int RANDOM_NUMBER = 12;
14 : addRandomNumber(10)
15 : class Dummmy{
int number =3;
public void setNumber(int number){this.number=number; }
public int getNumber(){return number;}
}
16 : Dummmy d = new Dummmy();
17 : d.setNumber(3);
18 : d.getNumber();
19 : Thread.sleep(1000);
20 : System.out.println("Hello");
21 : Thread.sleep(2000);
22 : System.out.println("Hello");
23 : new Thread(()->System.out.println("Hello")).start()
24 : CompletableFuture.runAsync(()->System.out.println("Hello")).thenRun(()->System.out.println("World"))
25 : 1/0
/history show all valid and invalid commands
jshell> /history
"hello world"
System.out.println($1)
$1+ " again"
$1= $1 + " again"
int sum = 1+2;
if(sum>0)
System.out.println("Positive")
if(sum>0)
System.out.println("Positive") else System.out.println("negative")
System.out.println("Positive") else System.out.println("negative");
System.out.println("Positive"); else System.out.println("negative");
if(sum>0)
System.out.println("Positive")
int negativeNumber(int n)
{
return -n;
}
negativeNumber(sum)
int addRandomNumber(int n)
{
return n + RANDOM_NUMBER;
}
addRandomNumber(10)
int RANDOM_NUMBER = 12;
addRandomNumber(10)
class Dummmy{
int number =3;
public void setNumber(int number){this.number=number; }
public int getNumber(){return number;}
}
Dummy dummy = new Dummy()
Dummy dummy = new Dummy();
Dummmy d = new Dummmy();
d.setNumber(3);
d.getNumber();
Thread.sleep(); System.out.println("Hello");
Thread.sleep(1000); System.out.println("Hello");
Thread.sleep(2000); System.out.println("Hello");
new Thread(()->System.out.println("Hello")).start()
CompletableFuture.runAsync(()->System.out.println("Hello")).thenRun(()->System.out.println("World"))
1/0
/list
/history
amsldasd
/history
jshell>
Display all variables
jshell> /vars
| int sum = 1
| String $2 = "Hello"
Using editor
jshell> /edit
See all the imports
jshell> /imports
| import java.io.*
| import java.math.*
| import java.net.*
| import java.nio.file.*
| import java.util.*
| import java.util.concurrent.*
| import java.util.function.*
| import java.util.prefs.*
| import java.util.regex.*
| import java.util.stream.*
Modularization is Java 9
What is a module ?
- a collection of code (packages) and data
- has a name (Generally a reverse DNS name)
- tells what is needs (requires)
- tells what is provides (exports)
Note:
You require modules
You Export Package
- Create 3 modules in your project.
- Introduce a main-info.jave file for each module in the root folder.
Require a module from JDK
module module1{
requires java.logging;
}
module-info.java
package com.Arithemetic.demo;
import java.util.logging.Logger;
public class ArithmeticOperation {
static Logger logger = Logger.getLogger(ArithmeticOperation.class.getName());
public static void add(int a, int b) {
logger.info("Sum::"+a+b);
}
}
package com.String.demo;
import java.util.logging.Logger;
public class StringOperation {
static Logger logger = Logger.getLogger(StringOperation.class.getName());
public static void concatAndReverseString(String string1, String string2) {
logger.info(new StringBuilder(string1 + " " + string2).reverse().toString());
}
}
Handshake between 2 modules
module module1{
requires java.logging;
exports com.Arithemetic.demo;
}
module module2{
requires module1;
}
package com.module2.demo;
import com.Arithemetic.demo.ArithmeticOperation;
public class Module2Demo {
public static void main(String[] args) {
ArithmeticOperation.add(1,2);
}
}
Restricting package access for a module
module module1{
requires java.logging;
exports com.Arithemetic.demo;
exports com.String.demo to module3;
}
com.String.demo is available to module3 and this package cannot be access in module 2
Exercise 1
- Practice following features of Java 9
- Private Methods in interface
- takeWhile and dropWhile methods in streams API
- ClosedRange
- Create a Stream using .iterator method apply some filter on it and Collect the result
- ifPresentOrElse with Optional
- or with Optional
- Convert Optional into Stream
- Use of method to create immutable collections
- Enhanced try block with AutoCloseable
- Try few jshell commands
- Perform handshake between 2 modules
Java 10
Local Variable Type inference
- One of the most visible enhancements in JDK 10 is type inference of local variables with initializers.
- Until Java 9 we have to mention the type of the local variable and insure that it was compatible with the initializer used to initialize it.
- In Java 10 we can mark the variable with var and the compiler infers the type of the variable.
var message = "Hello, java 10";
System.out.println(message instanceof String);
- Note that this feature is available only for local variables with the initializer. It cannot be used for member variables, method parameters, return types, et
var map = new HashMap<String, Integer>();
var list = new ArrayList<Integer>();
var set = new HashSet<String>();
Illegal use of var
var won't work without initializer
var n;
Nor would it work if initialized with null:
var empty=null;
It won't work for non-local variables:
public var empty=null;
Lambda expression needs explicit target type, and hence var cannot be used:
var p = (String s) -> s.length() > 10;
var arr = {1,2,3,4};
Same is the case with the array initializer:
Unmodifiable Collections
copyOf : java.util.List, java.util.Map and java.util.Set each got a new static method copyOf(Collection).
It returns the unmodifiable copy of the given Collection:
List<Integer> intList = new ArrayList<>();
intList.add(1);
intList.add(2);
intList.add(3);
intList.add(4);
List<Integer> unmodifiableCollection = List.copyOf(intList);
unmodifiableCollection.add(5);
toUnmodifiable : java.util.stream.Collectors get additional methods to collect a Stream into unmodifiable List, Map or Set
List<Integer> intList = Stream.of(1,2,3,4,5,6,7)
.filter(e->e%2==0)
.collect(Collectors.toUnmodifiableList());
Optional*.orElseThrow()
java.util.Optional, got a new method orElseThrow() which doesn't take any argument and throws NoSuchElementException if no value is present:
Stream.of(1,2,3,4,5,6,7).filter(e->e>8).findFirst().orElseThrow();
Java 11
String API additions
repeat() instance method repeats the string content.
String song = "we wish you a merry christmas!!!! ".repeat(3)+" and a happy new year";
System.out.println(song);
The strip() instance method returns a string with all leading and trailing whitespaces removed:
String whiteTrailString = "\n\t This is a string with white trails \u2005";
System.out.println(whiteTrailString.trim().equals("This is a string with white trails"));//false
System.out.println(whiteTrailString.strip().equals("This is a string with white trails"));//true
The isBlank() instance method returns true if the string is empty or contains only whitespace
String blackString = "\n\t ";
System.out.println(blackString.isBlank());
String multiLines = "This is line 1.\n This is line 2";
System.out.println("Total number of lines::"+multiLines.lines().count());
- The java.util.Collection interface contains a new default toArray method.
- This toArray method is also provided as stream terminal operation.
- It is a handy method to transform a collection or Stream to Arrays
toArray with Stream and Collection
List<Integer> integerList = Arrays.asList(1, 2, 3, 4);
Integer[] intArray = integerList.toArray(Integer[]::new);
System.out.println(Arrays.compare(intArray, new Integer[]{1,2,3,4}));
System.out.println(Arrays.toString(integerList.stream().filter(e -> e % 2 != 0).toArray()));
New IO methods introduced in Java 11
String path = "/Users/pulkitpushkarna/demo.txt";
try {
String fileContent = Files.readString(Path.of(path));
System.out.println(fileContent);
Files.writeString(Path.of(path),"This is third line.", StandardOpenOption.APPEND);
List<String> stringList = Files.readAllLines(Path.of(path));
stringList.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
java.net.http package has become standard feature in Java 11
HttpRequest httpRequest = HttpRequest
.newBuilder()
.uri(URI.create("http://dummy.restapiexample.com/api/v1/employee/1"))
.GET()
.build();
HttpClient httpClient = HttpClient.newBuilder().build();
try {
HttpResponse<String> httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
System.out.println(httpResponse.body());
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
Support for using the var keyword in lambda parameters was added in Java 11
BiFunction<Integer,Integer,Integer> function = (var a, var b)->a+b;
System.out.println(function.apply(1,2));
isEmpty method introduced Optional class
Optional<Integer> integerOptional= List.of(1,2,3,4).stream().filter(e->e>7).findFirst();
System.out.println(integerOptional.isPresent());
System.out.println(integerOptional.isEmpty());
Predicate Not Method in Streams
Optional<Integer> integerOptional= List.of(1,2,3,4)
.stream()
.filter(Predicate.not(e->e>7))
.findFirst();
System.out.println(integerOptional);
Java 12
String text = "Hello Guys ! This is Java 12 article.";
text = text.indent(15);
System.out.println(text);
text = text.indent(-20);
System.out.println(text);
- indent adjusts the indentation of each line based on the integer parameter.
- If the parameter is greater than zero, new spaces will be inserted at the beginning of each line.
- On the other hand, if the parameter is less than zero, it removes spaces from the begging of each line.
indent method
Transform Method
transform. It accepts a single argument function as a parameter that will be applied to the string.
String returnString = text.transform(string-> new StringBuilder(string)
.reverse().toString());
System.out.println(returnString);
File Mismatch method
It returns -1L if the files are identical
Path path1 = Files.createTempFile("file1",".txt");
Path path2 = Files.createTempFile("file2",".txt");
Files.writeString(path1,"Java 12 features");
Files.writeString(path2,"Java 12 features");
System.out.println(Files.mismatch(path1,path2));;
Teeing Collector
- It is a composite of two downstream collectors.
- Every element is processed by both downstream collectors.
- Then their results are passed to the merge function and transformed into the final result.
double mean = Stream.of(1,2,3,4,5)
.collect(Collectors.teeing(
Collectors.counting(),
Collectors.summingDouble(e->e+5),
(a,b)->b/a));
System.out.println(mean);
double result = (double)Stream.of(1,2,3,4,5)
.collect(
Collectors.teeing(Collectors.reducing(1,(a,b)->a*b),
Collectors.reducing(0,
(a,b)->a+b),(a,b)->a/b));
System.out.println(result);;
Compact Number Formatting
the CompactNumberFormat. It's designed to represent a number in a shorter form, based on the patterns provided by a given locale.
NumberFormat likesShort =
NumberFormat.getCompactNumberInstance(new Locale("en", "US"), NumberFormat.Style.SHORT);
likesShort.setMaximumFractionDigits(2);
System.out.println(likesShort.format(12345678));
NumberFormat likesLong =
NumberFormat.getCompactNumberInstance(new Locale("en", "US"), NumberFormat.Style.LONG);
likesLong.setMaximumFractionDigits(2);
System.out.println(likesLong.format(12345678));
Switch Expressions compact and more readable (Preview)
String dayOfWeek = "SUNDAY";
String day = switch (dayOfWeek){
case "MONDAY","TUESDAY","WEDNESDAY","THURSDAY","FRIDAY"->"WEEKDAY";
case "SATURDAY","SUNDAY"->"WEEKEND";
default -> throw new IllegalStateException("Unexpected value: " + dayOfWeek);
};
Pattern Matching with instanceof (Preview)
Object object = "Hello Java";
if(object instanceof String s){
System.out.println(s.length());
}
Exercise 2
- Perform Local Variable Type inferencing with var
- Create Unmodifiable Collections from modifiable Collections
- Try orElseThrow method with Optional
- Try out following String methods
- repeat
- strip
- isBlank
- lines
- Use toArray method to convert Stream and List into array
- Perform files operation using new readString and writeString methods.
- Perform Rest API GET call using java.net.http
- use Predicate.not with streams
- Try out indent and tranform methods of String
- Use file::mismatch method to compare 2 files.
Exercise 2 (Cont.)
- Use teeing collector with Streams
- Try out Compact Number Formatting
- Use Switch Expressions with Compact Syntax
- Use Pattern matching with instanceOf
Java 13
yield in switch expression
String dayOfWeek = "TUESDAY";
String day = switch (dayOfWeek) {
case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" -> {
System.out.println("Performing Some operations for this case");
yield "WEEKDAY";
}
case "SATURDAY", "SUNDAY" -> {yield "WEEKEND";}
default -> throw new IllegalStateException("Unexpected value: " + dayOfWeek);
};
System.out.println(day);
yield, we can now effectively return values from a switch expression. In case of multiple lines in
triple quote notation for text blocks
This will allow us to defined strings on multiple line without the need to escape new lines \n or use the + sign for string concatenation on multiple lines.
String multiLines = """
This is line 1.
This is line 2.
""";
System.out.println(multiLines);
String JSON_STRING = """
{"name": "Pulkit",
"age":31
}
""";
System.out.println(JSON_STRING);
java.lang.String now has three new methods
- stripIndent() – mimics the compiler to remove incidental white space
- translateEscapes() – translates escape sequences such as “\\t” to “\t”
- formatted() – works the same as String::format, but for text blocks
String html = "\t<html>\n" +
"\t\t<body>\n" +
"\t\t\t<p>Hello, world</p>\n" +
"\t\t</body>\n" +
"\t</html>";
System.out.println(html);
System.out.println(html.stripIndent());
String str = "\"Hello\\nWorld\"";
System.out.println(str);
System.out.println(str.translateEscapes());
System.out.println(String.format("Java %s", "12"));
System.out.println("Java %s".formatted("12"));
Java 14
Text Blocks (Preview)
text blocks now have two new escape sequences:
- \: to indicate the end of the line, so that a new line character is not introduced
- \s: to indicate a single space
String multiline = """
This is line 1.\
This is line 2.
""";
System.out.println(multiline);
String stringWithSpaces = "This is line with \s\sspaces";
System.out.println(stringWithSpaces);
Records (Preview)
- Passing immutable data between objects is one of the most common tasks in many Java applications.
- This required the creation of a class with boilerplate fields and methods, which were susceptible to trivial mistakes
- we can replace our repetitious data classes with records.
- Records are immutable data classes that require only the type and name of fields.
- The equals, hashCode, and toString methods, as well as the private, final fields, and public constructor, are generated by the Java compiler.
To create a Person record, we use the record keyword:
record Person(String name, String age){};
Person person = new Person("Pulkit","23");
This constructor can be used in the same way as a class to instantiate objects from the record:
We also receive public getters methods – whose names match the name of our field
Person person = new Person("Pulkit","23");
System.out.println(person.name());
System.out.println(person.age());
equals method returns true if the supplied object is of the same type and the values of all of its fields match:
Person person1 = new Person("Pulkit","23");
Person person2 = new Person("Pulkit","23");
System.out.println(person1.equals(person2));
hashCode method returns the same value for two Person objects if all of the field values for both object match
Person person1 = new Person("Pulkit","23");
Person person2 = new Person("Pulkit","23");
System.out.println(person1.hashCode());
System.out.println(person2.hashCode());
toString method that results in a string containing the name of the record, followed by the name of each field and its corresponding value in square brackets.
System.out.println(person);
While a public constructor is generated for us, we can still customize our constructor implementation.
This customization is intended to be used for validation and should be kept as simple as possible.
record Person(String name, String age){
//canonical constructor Java 15
Person{
Objects.requireNonNull(name);
Objects.requireNonNull(age);
}
public Person(String name) {
this(name, "Unknown");
}
};
Person person = new Person("Pulkit");
System.out.println(person);
we can also include static variables and methods in our records.
record Person(String name, int age) {
static int counter = 0;
static void incrementCounter() {
counter++;
}
Person {
incrementCounter();
}
};
new Person("Pulkit", 23);
new Person("Sunny", 24);
System.out.println(Person.counter);
We can also include instance methods in our records
record Person(String name, int age) {
String getOnlyName(){
return Person.this.name;
}
};
System.out.println(new Person("Sunny", 24).getOnlyName());
Java 15
Sealed Classes (Preview)
- The goal of sealed class is to allow individual classes to declare which types may be used as sub-types.
- This also applies to interfaces and determining which types can implement them.
- Sealed classes involve two new keywords — sealed and permits:
sealed class Base permits Child1,Child2{ }
final class Child1 extends Base{}
final class Child2 extends Base{}
// Child3 is not allowed in sealed hierarchy
final class Child3 extends Base{}
Every permitted class must be set with an explicit modifier. It can either be final, sealed or non sealed
- A permitted subclass that’s declared final cannot be extended further
- A permitted subclass that’s declared sealed can be extended further but only by classes that are permitted by the subclass.
- A permitted subclass may be declared non-sealed can be extended further by any class. The superclass cannot restrict the subclasses further down this class hierarchy.
sealed class Base permits Child1,Child2,Child3{ }
final class Child1 extends Base{}
sealed class Child2 extends Base permits GrandChild{}
non-sealed class Child3 extends Base{}
final class GrandChild extends Child2{}
//GrandChile2 not allowed in sealed hierarchy
class GrandChild2 extends Child2{}
Sealed Classes with Records
sealed interface Vehicle permits Car,Bike{
int numberOfWheels();
}
record Car() implements Vehicle {
@Override
public int numberOfWheels() {
return 4;
}
}
record Bike() implements Vehicle{
@Override
public int numberOfWheels() {
return 2;
}
}
public class Java15Demo {
public static void main(String[] args) {
Car car = new Car();
System.out.println(car.numberOfWheels());
Bike bike = new Bike();
System.out.println(bike.numberOfWheels());
}
}
Pattern Matching Type Checks with Records
sealed interface Vehicle permits Car,Bike{
int numberOfWheels();
}
record Car() implements Vehicle {
@Override
public int numberOfWheels() {
return 4;
}
}
record Bike() implements Vehicle{
@Override
public int numberOfWheels() {
return 2;
}
}
public class Java15Demo {
public static void main(String[] args) {
Object obj = new Car();
if(obj instanceof Vehicle vehicle && vehicle.numberOfWheels()>2){
System.out.println(vehicle.numberOfWheels());
}
}
}
Java 16
- The pattern matching for instanceof is a standard or product feature in Java 16.
- The record is finalized and becomes a standard feature.
- Java 16 introduces a new Stream.mapMulti method which allows you to replace elements in a stream with multiple elements.
Stream.of("hello","world").mapMulti((string,consumer)->consumer.accept(string));
System.out.println(Stream.of("hello","world","java")
.mapMulti((string,consumer)->{
if(string.length()>4) {
consumer.accept(string);
consumer.accept(string.toUpperCase());
consumer.accept(new StringBuilder(string).reverse().toString());
}
})
.collect(Collectors.toList()));;
Stream.of(1,2,3)
.mapMultiToInt((number,consumer)->{
IntStream.range(1,11).forEach(e->consumer.accept((Integer)(number *e)));
} )
.filter(e->e>15)
.forEach(System.out::println);
record Artist(String name) {}
record Album(String title, List<Artist> artistList) {}
record Pair(String album,String artist){}
List<Album> albums =
List.of(new Album("Album1",
List.of(new Artist("Artist1"), new Artist("Artist2"))),
new Album("Album2",
List.of(new Artist("Artist3"), new Artist("Artist4"))));
albums.stream().mapMulti((album, consumer) -> {
for (Artist artist : album.artistList()) {
consumer.accept(new Pair(album.title,artist.name));
}
}).forEach(System.out::println);
Exercise 3
- use yield with Switch Statement
- Create a String using Triple Quote notation
- Use following operations with String
- stripIndent
- translateEscapes
- formatted
- escape new line in triple quote text block
- Create a Record for Student with following Fields:
- id
- name
- standard
- Make sure that no null values should be used for initialization.
- Use equal and hashCode methods with Student records
Exercise 3 (Cont.)
- Use a Sealed class Class concept to create a class hierarchy
- Mark Child classes as final, sealed and non sealed and observe their behaviour
- Try out MultiMap intermediate method of Stream
Java 9-16 all useful features
By Pulkit Pushkarna
Java 9-16 all useful features
- 852