Java 8 - Strings, IO's and other bits and pieces
Hi, I am Malathi Boggavarapu working at Volvo Group and i live in Gothenburg, Sweden. I have been working on Java since several years and had vast experience and knowledge across various technologies. In this course we will discuss about Strings, IO enhancements, Comparators and many more. So let's get started
Strings, IO's and other bits and pieces
Java 8 is not only about lambda expressions and Streams.
String class
Java I/O package
Collection interface
Comparators - New way of writing them in Java8.
Numbers
Map
Annotations
IntStream stream = s.chars(); // creates a stream on letters of s
stream.mapToObj(letter -> (char)letter)
.map(Character::toUpperCase)
.forEach(System.out::print);
Output will be HELLO WORLD!
String s1 = "Hello"
String s2 = "World"
String s = s1 + s2;
The above way of string concatenation is not efficient and should not be used because of the multiple creations/deletions of intermediary strings. So StringBuffer class is used using append method.
But StringBuffer is synchronized. So in Java5 StringBuilder is used which is not synchronized and would be better to append the strings than StringBuffer
Join Strings with builtin seperator.
StringJoiner sj = new StringJoiner(",");
s1.add("one").add("two").add("three")
System.out.println(sj.toString()); // outputs one, two, three
We can also pass prefix and suffix as arguments to StringJoiner class
StringJoiner sj = new StringJoiner(",", "{", "}");
s1.add("one").add("two").add("three")
System.out.println(sj.toString()); // outputs {one, two, three}
StringJoiner can also be used from String class but we can not add prefix and suffix to the join method
String s = String.join(",", "one", "two", "three");
we can also write the above line as follows
String s[] = {"one", "two", "three"};
String s = String.join(",", s);
The lines() method has been added to the BufferedReader class
try(
BufferedReader reader = new BufferedReader(new FileReader(new File("D:/debug.log")));
){
Stream<String> stream = reader.lines(); // new method in Java 8
stream.filter(line -> line.contains("ERROR")).findFirst().ifPresent(System.out::println)
}catch(IOExeption e){
.....
}
If we see the above code, we write BufferedReader code as an argument of try block. This is the feature in Java7. In this way, we no need to explicitly close the reader of the inputStream. It is automatically done for us in the bytecode of java class.
lines() method is newly added in Java8 which returns the stream of lines from debug.log file
And the stream is operated using several intermediary methods findFirst,isPresent...
File.lines(path)
----------------
Path path = Paths.get("D:", "tmp", "debug.log");
try(
Stream<String> stream = File.lines(path);
){
Stream<String> stream = reader.lines(); // new method in Java 8
stream.filter(line -> line.contains("ERROR")).findFirst().ifPresent(System.out::println)
}catch(IOExeption e){
.....
}
Stream implements AutoCloseable and will close the underlying file.
Method File.list(path) - Used to read the directory files taking Path as an argument but it does not read the sub directories inside the directory. But no problem, we can acheive this using different method available in java8
Path path = Paths.get("D:", "windows");
try(Stream<Path> stream : Files.list(path)){
stream.filter(path -> path.tiFile().isDirectory()).forEach(System.out::println);
}catch(Exception e){
......
}
Files.walk(path) method - Used to list the files even from sub directories from a directory. The code is same as above except that we use Files.walk(path)
Path path = Paths.get("D:", "windows");
try(Stream<Path> stream : Files.walk(path)){
stream.filter(path -> path.tiFile().isDirectory()).forEach(System.out::println);
}catch(Exception e){
......
}
we can also limit the depth of exploration of sub directories inside a directory by simply passing an additional parameter to walk method
Ex: Follow the same code as above but pass an integer to walk method as below
Files.walk(path, 2). It limits exploration of sub directories. Try it!!
New methods in Iterable, Collection and List
------------------------------------------------------------
New method on Iterable
forEach() - strings.forEach(System.out::println);
New methods on Collection
removeIf() - It accepts a predicate and return boolean value
Collection<String> strings = Arrays.asList("one", "two", "three", "four", "five");
Collection<String> list = new ArrayList(strings);
boolean b = list.removeIf(s -> s.length() > 4);
System.out.println(list.stream().collect(Collectors.joining(",")));
New methods on list
------------------------------
replaceAll() method - It takes function as a parameter which is special type of function called unary operator that takes element from that list and returns another element of the same type. Each element of the list is processed by the function
Ex:
List<String> strings = Arrays.asList("one", "two", "three", "four", "five");
List<String> list = new ArrayList(strings);
list.replaceAll(String::toUpperCase);
System.out.println(list.stream().collect(Collectors.joining(",")));
Method sort() - Sorts content of a list by providing Comparator
Example:
list.sort(Comparator.naturalOrder());
System.out.println(list.stream().collect(Collectors.joining(",")));
Comparator is an interface. In java 7, we should implement our own Comparator interface to compare and arrange the elemnts in an order. We need to address all sort of conditions on the objects that we compare.
Example: while we compare two objects using a field called lastName (Ex: Person), and if they are equal, we should consider some other fields on the objects to compare with.
Also we should add null check on the objects while comparing
All these problems are addressed easily in java8 using comparing method
Comparator<Person> compareLastName =
Comparator.comparing(Person::getLastName)
.thenComparing(Person::getFirstName)
The above code is much better and is very readable. If we see the code, if lastName is same for two objects, thenComparing method is called and compare the objects depending on firstName. thenComparing is used to chain the comparisons of different fields.
thenComparing is the default method of the interface Comparator
We can reverse a given comparator using reversed method. This is also a default method on interface
Comparator<Person> comp = ....;
Comparator reversedComp = comp.reversed();
naturalOrder method is static method of Comparator interface. It compares comparable objects, for example Strings in a natural order - alphabetical order
Comparator comp = Comparator.naturalOrder();
nullsFirst is a static method of Comparator interface. If the list have null values, then they are put at the starting of the list.
Comparator comp = Comparator.nullsFirst(Comparator.naturalOrder());
nullsLast is a static method of Comparator interface. If the list have null values, then they are put at the end of the list
Comparator comp = Comparator.nullsLast(Comparator.naturalOrder());
Numbers
-------------
In java we have primitive types such int, float, double, char, short and they all got associated wrapper type
Java8 provides new useful methods such as sum, max and min
long max = Long.max(1L, 2L);
The methods are useful to create reduction operations
BinaryOperator<Long> max = (i1, i2) -> i1 + i2; // we can write it as Long::sum
Following is the solution in jdk7 to compute hashcode for long variables.
long l = 3141592653589793238L;
int hash = new Long(l).hashCode();
Here there is costly boxing and unboxing of primitive type to compute the hashcode.
So we have a method in java8 called hashCode which accepts the primitve type as an argument to compute hashcode for primitive types. See below example.
long l = 3141592653589793238L;
int hash = Long.hashCode(l);
This method is available on 8 wrapper types.
That's all about this course. Hope it is helpful. Please post your comments below.
Happy Learning!!
String class
Java I/O package
Collection interface
Comparators - New way of writing them in Java8.
Numbers
Map
Annotations
Strings in Java 8
String s = "Hello world!"IntStream stream = s.chars(); // creates a stream on letters of s
stream.mapToObj(letter -> (char)letter)
.map(Character::toUpperCase)
.forEach(System.out::print);
Output will be HELLO WORLD!
StringJoiner
String s1 = "Hello"
String s2 = "World"
String s = s1 + s2;
The above way of string concatenation is not efficient and should not be used because of the multiple creations/deletions of intermediary strings. So StringBuffer class is used using append method.
But StringBuffer is synchronized. So in Java5 StringBuilder is used which is not synchronized and would be better to append the strings than StringBuffer
Join Strings with builtin seperator.
StringJoiner sj = new StringJoiner(",");
s1.add("one").add("two").add("three")
System.out.println(sj.toString()); // outputs one, two, three
We can also pass prefix and suffix as arguments to StringJoiner class
StringJoiner sj = new StringJoiner(",", "{", "}");
s1.add("one").add("two").add("three")
System.out.println(sj.toString()); // outputs {one, two, three}
StringJoiner can also be used from String class but we can not add prefix and suffix to the join method
String s = String.join(",", "one", "two", "three");
we can also write the above line as follows
String s[] = {"one", "two", "three"};
String s = String.join(",", s);
Java I/O enhancements
1) Reading text filesThe lines() method has been added to the BufferedReader class
try(
BufferedReader reader = new BufferedReader(new FileReader(new File("D:/debug.log")));
){
Stream<String> stream = reader.lines(); // new method in Java 8
stream.filter(line -> line.contains("ERROR")).findFirst().ifPresent(System.out::println)
}catch(IOExeption e){
.....
}
If we see the above code, we write BufferedReader code as an argument of try block. This is the feature in Java7. In this way, we no need to explicitly close the reader of the inputStream. It is automatically done for us in the bytecode of java class.
lines() method is newly added in Java8 which returns the stream of lines from debug.log file
And the stream is operated using several intermediary methods findFirst,isPresent...
File.lines(path)
----------------
Path path = Paths.get("D:", "tmp", "debug.log");
try(
Stream<String> stream = File.lines(path);
){
Stream<String> stream = reader.lines(); // new method in Java 8
stream.filter(line -> line.contains("ERROR")).findFirst().ifPresent(System.out::println)
}catch(IOExeption e){
.....
}
Stream implements AutoCloseable and will close the underlying file.
Reading Directory Entries
Method File.list(path) - Used to read the directory files taking Path as an argument but it does not read the sub directories inside the directory. But no problem, we can acheive this using different method available in java8
Path path = Paths.get("D:", "windows");
try(Stream<Path> stream : Files.list(path)){
stream.filter(path -> path.tiFile().isDirectory()).forEach(System.out::println);
}catch(Exception e){
......
}
Files.walk(path) method - Used to list the files even from sub directories from a directory. The code is same as above except that we use Files.walk(path)
Path path = Paths.get("D:", "windows");
try(Stream<Path> stream : Files.walk(path)){
stream.filter(path -> path.tiFile().isDirectory()).forEach(System.out::println);
}catch(Exception e){
......
}
we can also limit the depth of exploration of sub directories inside a directory by simply passing an additional parameter to walk method
Ex: Follow the same code as above but pass an integer to walk method as below
Files.walk(path, 2). It limits exploration of sub directories. Try it!!
New methods in Iterable, Collection and List
------------------------------------------------------------
New method on Iterable
forEach() - strings.forEach(System.out::println);
New methods on Collection
removeIf() - It accepts a predicate and return boolean value
Collection<String> strings = Arrays.asList("one", "two", "three", "four", "five");
Collection<String> list = new ArrayList(strings);
boolean b = list.removeIf(s -> s.length() > 4);
System.out.println(list.stream().collect(Collectors.joining(",")));
New methods on list
------------------------------
replaceAll() method - It takes function as a parameter which is special type of function called unary operator that takes element from that list and returns another element of the same type. Each element of the list is processed by the function
Ex:
List<String> strings = Arrays.asList("one", "two", "three", "four", "five");
List<String> list = new ArrayList(strings);
list.replaceAll(String::toUpperCase);
System.out.println(list.stream().collect(Collectors.joining(",")));
Method sort() - Sorts content of a list by providing Comparator
Example:
list.sort(Comparator.naturalOrder());
System.out.println(list.stream().collect(Collectors.joining(",")));
Comparators
Comparator is an interface. In java 7, we should implement our own Comparator interface to compare and arrange the elemnts in an order. We need to address all sort of conditions on the objects that we compare.
Example: while we compare two objects using a field called lastName (Ex: Person), and if they are equal, we should consider some other fields on the objects to compare with.
Also we should add null check on the objects while comparing
All these problems are addressed easily in java8 using comparing method
Comparator<Person> compareLastName =
Comparator.comparing(Person::getLastName)
.thenComparing(Person::getFirstName)
The above code is much better and is very readable. If we see the code, if lastName is same for two objects, thenComparing method is called and compare the objects depending on firstName. thenComparing is used to chain the comparisons of different fields.
thenComparing is the default method of the interface Comparator
We can reverse a given comparator using reversed method. This is also a default method on interface
Comparator<Person> comp = ....;
Comparator reversedComp = comp.reversed();
naturalOrder method is static method of Comparator interface. It compares comparable objects, for example Strings in a natural order - alphabetical order
Comparator comp = Comparator.naturalOrder();
nullsFirst is a static method of Comparator interface. If the list have null values, then they are put at the starting of the list.
Comparator comp = Comparator.nullsFirst(Comparator.naturalOrder());
nullsLast is a static method of Comparator interface. If the list have null values, then they are put at the end of the list
Comparator comp = Comparator.nullsLast(Comparator.naturalOrder());
Numbers
-------------
In java we have primitive types such int, float, double, char, short and they all got associated wrapper type
Java8 provides new useful methods such as sum, max and min
long max = Long.max(1L, 2L);
The methods are useful to create reduction operations
BinaryOperator<Long> max = (i1, i2) -> i1 + i2; // we can write it as Long::sum
Hashcode computation
Hashcode of integer is an integer itself. But we need to follow special algorithm to generate hascode of LongFollowing is the solution in jdk7 to compute hashcode for long variables.
long l = 3141592653589793238L;
int hash = new Long(l).hashCode();
Here there is costly boxing and unboxing of primitive type to compute the hashcode.
So we have a method in java8 called hashCode which accepts the primitve type as an argument to compute hashcode for primitive types. See below example.
long l = 3141592653589793238L;
int hash = Long.hashCode(l);
This method is available on 8 wrapper types.
That's all about this course. Hope it is helpful. Please post your comments below.
Happy Learning!!
Comments
Post a Comment