Practical Java 8 - Paulo Silveira - E-Book

Practical Java 8 E-Book

Paulo Silveira

0,0

Beschreibung

Are you a programmer fluent in Java? It's time to take the next step! Almost 20 years after it's first version, there is a new Java with important news! Amongst the main new resources, there are the default methods, method references and lambdas. They are simple concepts, but bring important possibilities. In the book we will explore various advancements found in Java 8. Always using practical examples and presenting real usage cases, we migrate the day-to-day legacy code to the new Java 8 functional paradigm. With this triad of concepts, the API managed to evolve in an interesting manner. The java.util.stream and java.util.function packages are deeply explored, presenting simple ways to work with collections and other data structures. Streams and Collectors will be part of your routine and will become as essential as Collections and the java.io currently are to your applications. Lastly, we'll see how the new API java.time comes to change from water to wine the way how we work with dates and times.

Sie lesen das E-Book in den Legimi-Apps auf:

Android
iOS
von Legimi
zertifizierten E-Readern

Seitenzahl: 162

Das E-Book (TTS) können Sie hören im Abo „Legimi Premium” in Legimi-Apps auf:

Android
iOS
Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Sumário

Capítulo 1: Java 8

1.1 Hold your horses!

1.2 Access the code and talk to us!

Capítulo 2: Hello Lambda!

2.1 The old way and the new way of doing loops

2.2 Let Lambda in!

Capítulo 3: Functional Interfaces

3.1 Another Example: listeners

3.2 Your very own functional interface

3.3 The @FunctionalInterface annotation

3.4 Digging deeper: the first details

Capítulo 4: Default Methods

4.1 The forEach method in the Iterable interface

4.2 The Consumer interface doesn’t have only one method!

4.3 Another new method in Collection: removelf

4.4 Multiple Inheritance?

Capítulo 5: Sorting in Java 8

5.1 Comparators using lambda

5.2 The List.sort method

5.3 Static methods in the Comparator Interface

5.4 Knowing the Comparator.comparing better

5.5 Sorting by score and the autoboxing

Capítulo 6: Method References

6.1 Turning all users into moderators

6.2 Comparing in an even lighter way

6.3 Composing comparators

6.4 Referencing instance methods

6.5 Referencing methods that receive arguments

6.6 Referencing constructors

6.7 Other types of references

Capítulo 7: Streams and Collectors

7.1 Making the top 10 users with highest scores moderators

7.2 Streams: making the users with a score higher than 100 moderators

7.3 How to get a List back?

7.4 Collectors

7.5 Advanced: why isn’t there a toList in Stream?

7.6 Listing only the scores of all users by using map

7.7 InStream and the Streams family

7.8 Optional in java.util

Capítulo 8: More operations with Streams

8.1 Sorting a Stream

8.2 Many operations in Stream are lazy!

8.3 what is the advantage of lazy methods?

8.4 Seeing at the pipeline executing with peek

8.5 Reduction operations

8.6 Learning about other Stream methods

8.7 Primitive and infinite streams

8.8 Practicing what we learn with java.nio.file.Files

8.9 FlatMap

Capítulo 9: Mapping, partitioning, grouping, and parallelizing

9.1 Collectors generating maps

9.2 groupingBy and partitioningBy

9.3 Running the pipeline in parallel

9.4 Nondeterministic operations and ordered streams

Capítulo 10: Enough with Calendar! New date API

10.1 Java.time comes from Joda Time

10.2 Working with dates fluently

10.3 Enums instead of constants

10.4 Formatting in the new date API

10.5 Invalid dates

10.6 Duration and Period

10.7 Differences from Joda Time

Capítulo 11: A payment model with Java 8

11.1 A digital goodies store

11.2 Reducing BigDecimal into sums

11.3 Best selling products

11.4 Value generated by product

11.5 What are the products of each customer?

11.6 Which one is our most special client?

11.7 Reports with dates

11.8 Subscription System

Capítulo 12: Appendix: more Java 8 with reflection, JVM, APIs, and limitations

12.1 New details in the language

12.2 What is the type of a Lambda expression?

12.3 Inference limitations in Lambda

12.4 End of PermGen

12.5 Reflection: parameter names

Go to Code Crushing and see our other e-books - www.codecrushing.com.

Capítulo 1: Java 8

It has been almost 20 years since the first version of Java was launched in 1996.

With the arrival of Java 5 in 2004, the programming language underwent significant changes -- especially with Generics, Enums, and Annotations.

With its 2014 incarnation, Java 8, the same scenario occurs. We now face new possibilities with the introduction of Lambda and Method References, in addition to other small changes. The Collections API, which includes the same main interfaces since 1998, went through a significant upgrade with the introduction of Streams and default methods.

In this book, you will have the chance to practice Java 8 extensively. It’s time to start programming, but first you will need to download and install the Java platform:

http://www.oracle.com/technetwork/java/javase/downloads/

You can access the Java 8 API documentation here:

http://docs.oracle.com/javase/8/docs/api/

Eclipse supports Java 8 since the Luna (4.4) version. You will need the following update for Kepler (4.3):

https://wiki.eclipse.org/JDT/Eclipse_Java_8_Support_For_Kepler

Eclipse still has some minor bugs when it comes to performing more complicated inferences, but Netbeans and IntelliJ have updated their Java 8 versions.

To practice the syntax, you can choose to complete the tests and examples from the book with a simple text editor.

1.1 Hold your horses!

If you expect something on the scale of Scala, Clojure, or C#, be prepared for disappointment. Java’s legacy and relatively young age, besides its lack of value types and reification of Generics, preclude the use of certain strategies. The Java Development Team takes great care to keep the syntax simple, as to avoid obscure features that would only bring little gain. (In our view, this makes perfect sense.)

On the other hand, it is amazing what has been achieved with the release of Java 8. You might be pleasantly surprised by some of the codes and approaches used. The focus is not breaking the compatibility of legacy Java code, while being the least intrusive with regards to the older APIs. Its new feature, the Streams, will play a crucial role in this elegant upgrade.

What was left out of Java 8?

In order to better break down Java 8’s specifications into smaller tasks, the JEPs (JDK Enhancement Proposals) have been created -- the inspiration came from the Python community’s PEPs. You can find those in a list of proposals here:

http://openjdk.java.net/jeps/0

As you can see, there are many new features in JDK8. Unfortunately, not all of these features had enough time to ripen. Among the JEPs, the Value Objects were left out:

http://openjdk.java.net/jeps/169

That was also the case for the use of literals when working with Collections:

http://openjdk.java.net/jeps/186

Among other ideas left out, there were several improvements to the already built-in Garbage Collectors, as well as the possible reification of Generics.

In any case, the absolute majority of the JEPs made it to the final version and were released. Throughout the book, we will see the major changes made to the language and the new APIs.

1.2 Access the code and talk to us!

The source code for each chapter can be found here:

https://github.com/codeslashers/java8

We recommend that you alone write all the codes presented in this book so as to practice the API and syntax. We also advise you to perform different tests from those suggested.

Here is a forum where you will be able to discuss with us or send us your suggestions or comments:

https://groups.google.com/forum/#!forum/codeslashers-java8

Capítulo 2: Hello Lambda!

Instead of starting the course with theory, you should first get a feel of how Java 8 will change your way of programming.

2.1 The old way and the new way of doing loops

It is important that you follow the book and recreate the code presented. This way, the syntax will become more natural and familiar to you.

Open your favorite text editor. Let’s create an entity and run examples based on it. Doing so, we will have the class User with three basic attributes: reputationScore, name, and boolean becomeModerator, indicating that this user will be a moderator in our system, just like this:

1 classUser{ 2 3 privateintreputationScore; 4 privateStringname; 5 privatebooleanbecomeModerator; 6 7 publicUser(Stringname,intreputationScore){ 8 this.reputationScorereputationScore; 9 this.namename;10 becomeModeratorfalse;11 }12 13 publicintgetReputationScore(){14 returnreputationScore;15 }16 17 publicStringgetName(){18 returnname;19 }20 21 publicvoidbecomeModerator(){22 becomeModeratortrue;23 }24 25 publicbooleanisModerator(){26 returnbecomeModerator;27 }28 }

We decided not to make the class public. This way, if you are in a simple text editor, you can create your tests in a public class within the same file.

Let’s handle a few users with their different names and scores and print each one of them out. We will do this the usual way, the way we already know, without using any of Java 8’s new features.

1 publicclassChapter2{ 2 3 publicstaticvoidmain(String...args){ 4 5 Useruser1newUser("Paulo Silveira",150); 6 Useruser2newUser("Rodrigo Turini",120); 7 Useruser3newUser("Guilherme Silveira",190); 8 9 List<User>usersArrays.asList(user1,user2,user3);10 11 for(Useruser:users){12 System.out.println(user.getName());13 }14 }15 }

We omit two imports from java.util.List and java.util.Arrays. They won’t be mentioned in this book, but we will warn you whenever new Java 8 packages come up.

Arrays.asList is a simple way of creating a fixed List. But you could have created a new ArrayList and added each user to it.

The for we are making is pretty simple. Since Java 5, we can navigate through any array or collection (actually, in any kind of object that implements the java.lang.Iterable interface).

A new method for all collections: forEach

With Java 8, we have access to a new method. forEach. Where does it come from? We will discuss this later. First, let’s use it. We can do this:

1 users.forEach(...);

What will it do for each user? Print the name. But what is the argument this method forEach receives?

It receives an object of the type java.util.function.Consumer, with its only method, the accept. Consumer is a new Java 8 interface, like the entire java.util.function package, which will be discussed later.

Let’s create this Consumer before using the new forEach:

1 classDisplayerimplementsConsumer<User>{2 publicvoidaccept(Useru){3 System.out.println(u.getName());4 }5 }

We created a class that implements this new Java 8 interface. It is quite trivial, having accept as the only method, and it is responsible for taking an object type User and using it. “Using” here refers to performing a task that makes sense to you. In our case, it means to show the user’s name on the standard output. After that, we instantiate this class and pass the reference to the expected forEach method:

1 DisplayerdisplayernewDisplayer();2 users.forEach(displayer);

We know it’s common to use Anonymous classes for these simpler tasks. Instead of creating a class Displayer just for this, we can do everything at once:

1 Consumer<User>displayernewConsumer<User>(){2 publicvoidaccept(Useru){3 System.out.println(u.getName());4 }5 };6 7 users.forEach(displayer);

This will generate a .class with a strange name, for example, Chapter2$1.class. Since we can’t refer to a name for this class, we call it an Anonymous class, as you may already know.

The code is still big. It seems that the old for was more succinct. We can reduce this code a little bit more by avoiding the creation of the local variable displayer:

1 users.forEach(newConsumer<User>(){2 publicvoidaccept(Useru){3 System.out.println(u.getName());4 }5 });

Done! It is a little shorter, but it’s still sufficiently wordy.

2.2 Let Lambda in!

Simply put, a Lambda in Java 8 is a simpler way to implement an interface that has a single method. In our case, the interface Consumer is a good candidate.

That is, instead of writing:

1 Consumer<User>displayernewConsumer<User>(){2 publicvoidaccept(Useru){3 System.out.println(u.getName());4 }5 };

We can write this in a more direct way:

1 Consumer<User>displayer2 (Useru)->{System.out.println(u.getName());};

The excerpt (User u) -> {System.out.println(u.getName());}; is a Lambda of Java 8. The compiler notices that you are attributing it to a Consumer<User> and inserts the code in the single method this interface has defined. Notice that we didn’t even mention the accept method! This is inferred during the compilation process.

We can go even further. The compiler can also infer the type without the need to use User or brackets:

1 Consumer<User>displayer2 u->{System.out.println(u.getName());};

Not satisfied? If the block between { } contains only one statement, we can omit it and also remove the semicolon:

1 Consumer<User>displayer2 u->System.out.println(u.getName());

Now it is even possible to write everything on a single line:

1 Consumer<User>displayeru->System.out.println(u.getName());

So u -> System.out.println(u.getName()) refers to the same Lambda as (User u) -> {System.out.println(u.getName());} if it is assigned to a Consumer<User>. We can pass this code excerpt directly to users.forEach instead of declaring a temporary variable displayer:

1 users.forEach(u->System.out.println(u.getName()));

Difficult? Certainly not. But it may take a few weeks until you get used to the syntax and the different ways of using it. We will see some variations, work more with the API, and learn how it is implemented (which is a little different from Anonymous classes). If you observe the .class generated, you may notice that the compiler didn’t create many files Chapter2$N.class, as is usually the case for the Anonymous classes.

Let’s see an example that will clarify this. You can, instead of printing the names of all users, make them moderators.

1 users.forEach(u->u.becomeModerator());

Note that the variable u can’t have been declared in the same scope as the invocation of forEach, because the Lambda can capture outer variables, as we shall see.

In the next chapter, we will work more with Lambda and you will practice your syntax. You will also discover other basic scenarios of its usage along with the concept of Functional Interface.

Capítulo 3: Functional Interfaces

Note that the Consumer<User> interface, for example, has only one abstract method, accept. That’s the reason why, when you do the following forEach, the compiler knows exactly what method should be implemented within the Lambda’s body:

1 users.forEach(u->System.out.println(u.getName()));

But what if the Consumer<User> interface had two methods? The fact that this interface only has one method isn’t a coincidence; it is necessary for the compiler to translate it to a Lambda expression. So we can say that any Java interface that has only one abstract method can be instantiated as a Lambda code!

This applies even to the pre-Java 8 interfaces like Runnable:

1 publicinterfaceRunnable{2 publicabstractvoidrun();3 }

Just a reminder: by default, all methods of a Java interface are public and abstract. We will see later that there is a new kind of method in interfaces.

Normally, we write the following excerpt to instantiate a Thread and a Runnable that counts from 0 to 1000:

1 RunnablernewRunnable(){2 publicvoidrun(){3 for(inti0;i<=1000;i++){4 System.out.println(i);5 }6 }7 };8 newThread(r).start();

The Runnable interface has only one abstract method. An interface that fits this requirement is now known as a functional interface! It can always be instantiated with a Lambda expression:

1 Runnabler()->{2 for(inti0;i<=1000;i++){3 System.out.println(i);4 }5 };6 newThread(r).start();

We could go further and do everything in a single statement, although it may be a little less easy to read:

1 newThread(()->{2 for(inti0;i<=1000;i++){3 System.out.println(i);4 }5 }).start();

As you already know, there is a new package in Java 8, java.util.function, with a range of functional interfaces that can and should be used. We will see several of them over the course of our study.

3.1 Another Example: listeners

Another very common use of the Anonymous class is when we need to add an action by clicking on an object of the java.awt.Button type. For this, we need to implement an ActionListener. You might have already seen a code similar to this:

1 button.addActionListener(newActionListener(){2 publicvoidactionPerformed(ActionEvente){3 System.out.println("click event fired");4 }5 });

We use the ActionListener interface as nothing more than a return function, and because of its single method structure, it fits the requirement for a functional interface:

1 publicinterfaceActionListenerextendsEventListener{2 /**3 * Invoked when an action occurs.4 */5 publicvoidactionPerformed(ActionEvente);6 }

Just as with any functional interface, we can also represent it as a Lambda expression:

1 button.addActionListener((event)->{2 System.out.println("click event fired");3 });

As previously seen, this expression can be simplified even further by taking out the parentheses in the single argument. We can also remove the {} and ;:

1 button.addActionListener(2 event->System.out.println("click event fired"));

Done! Now we are attributing the same action to the button, but replacing the 5 lines with an anonymous class by a single line lambda expression.

As for ActionListener that already exists and is commonly used in the pre-Java 8 versions, there are several other Java interfaces that have the same structure of a single method, such as java.util.Comparator, java.util.concurrent.Callable, and java.io.FileFilter -- besides the java.lang.Runnable interface we’ve already mentioned.

Even without having anything changed in its internal structure, all of these interfaces can be called Functional Interfaces since this new language version!

3.2 Your very own functional interface

You don’t need to do anything special to make an interface functional. The compiler readily identifies the interface as functional because of its structure.

Imagine that we have a Validator<T> interface with a method that validates(T t) and returns a boolean:

1 interfaceValidator<T>{2 booleanvalidates(Tt);3 }

We usually use it by creating an Anonymous class, like this:

1 Validator<String>zipCodeValidatornewValidator<String>(){2 publicbooleanvalidates(Stringvalue){3 returnvalue.matches("[0-9]{5}-?([0-9]{4})?");4 }5 };

How can we use this interface with Lambda and Java 8? What do we need to change in its declaration?

The answer is simple: absolutely nothing. As said before, because of the interface’s single abstract method, it is already considered a Functional Interface, which means it can be instantiated through a Lambda expression! See below:

1 Validator<String>zipCodeValidator2 value->{3 returnvalue.matches("[0-9]{5}-?([0-9]{4})?");4 };

To try this, you can run in a simple main method the code zipCodeValidator.validates("12345-1234");.

Our Lambda is a little big. As already seen, when there is a single statement, we can summarize it. That is the case even if it’s a return ! We can remove the return