📜 ⬆️ ⬇️

What Java 8 prepares for us

Let's go through the new products and re-code in a new way.

So let's start on the list.

Suppose there is a list.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6); 


Now let's remember how we iterated in the old days:
 for (int i = 0; i < numbers.size(); i++){ System.out.println(numbers.get(i)); } 

')
Everything is great, but it is very easy to stumble and put <= instead of <or start from 1 instead of 0. In the above code, we completely control the mechanics, we keep in mind all the moving parts. This is good in many cases, and none of us chose this in Java 5, only added sugar.

 for(int num:numbers){ System.out.println(num); } 


In Java 8, they still don’t select anything, but they offer a “declarative” approach, which means that we declare what we want to do, and we assign all the mechanics to the JVM.

  numbers.forEach(value -> System.out.println(value)); 


Note that the example uses a lambda expression. About him in the next paragraph. Many have already seen forEach in many languages ​​and libraries. So, forEach allows us to express in one line “here's a collection for you, apply this expression to all its elements” (declarative approach), and not “starting with the first and ending with the last, go through one by one and use each element”.

Now about lambda expressions.

Very tasty innovation that allows you to replace anonymous classes with functions.

Consider the example already given above:
  numbers.forEach(value -> System.out.println(value)); 


if there were no lambda expressions, then this example would look like this:
 numbers.forEach(new Consumer<Integer>() { @Override public void accept(Integer integer) { System.out.println(integer); } @Override public Consumer<Integer> andThen(Consumer<? super Integer> after) { return null; } }); 


It's hard, isn't it? But back to the simple one-line expression, and here you can still simplify something: why should we mention value twice, if it is so clear that there can be no other variable.
 numbers.forEach(System.out::println); 


Yes, yes, we passed the method as a function (*). So we said: "here's your method, apply it in a cycle."

Here are a couple of examples of replacing anonymous classes with functions:

Thread Creation:
 new Thread(SomeClass::runSomething).start(); 


Sorting with comparator
 Collections.sort(numbers, (o1, o2)-> o2.compareTo(o1)); 


Changes in the Collections Framework

Having started lambda expressions, let's move on to the novelties in the Collections Framework. Suppose we need to calculate the sum of all the numbers in the list multiplied by two. Without thinking twice, we create a piece of code:

  List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6); int sum = 0; for (int num : numbers) { sum += num * 2; } 


Now let's turn to the declarative approach:
 int result = numbers.stream(). mapToInt(value->value*2). sum(); 

Wait, is it a map-reduce? He is. Let us analyze in order. So mapToInt performs a map operation, as a result of which elements become multiplied by two. sum is a reduce conversion available only for integers.

Suppose an order is received to modify the code and process only even, and odd ones to filter.
  System.out.println(numbers.stream(). filter(value -> value % 2 == 0). mapToInt(value -> value * 2). sum()); 


now, on the contrary, odd count, and even count:
  System.out.println(numbers.stream(). filter(value -> value % 2 != 0). mapToInt(value -> value * 2). sum()); 


another new language feature

We are used to the interface telling us “what are we going to do,” but does nothing on its own. In Java 8, the interface sometimes does something.

Here's a little example:
 public interface IFly { public void takeOff(); public default void cruise() { System.out.println("IFly.cruise"); }; public void turn(); public void land(); } 


Those who programmed in C ++ and read Björn Starstrup will ask the question: “what about the diamond problem?”. The question is interesting. And the answer is.

Suppose a class inherits two interfaces, and each of them has a default method. When compiling, an error will occur.

  public interface A { default void hello() { System.out.println("Hello World from A"); } } public interface B { default void hello() { System.out.println("Hello World from B"); } public class D implements A,B {} 


Let's look at another example: the triangle
  public interface A { default void hello() { System.out.println("Hello World from A"); } } public interface B extends A { default void hello() { System.out.println("Hello World from B"); } } public class C implements B, A { public static void main(String... args) { new C().hello(); } } 


In this case, the closest one in the hierarchy will win, that is, interface B. Well, if you want to use interface method A, you need to explicitly specify

 A.super.hello(); 


Let us consider the third example: there is a conflicting method in the abstract class and interface. The rule is that class always wins.

Thus the problem is solved:


Just a couple of snacks


Base64, how long the compiler gave us formidable messages about outdated sun.misc.Base64 and we had to use Apache libraries for seemingly simple things.
Now the issue is resolved: java.util.Base64
 Base64.getEncoder().encode(new byte[]{1, 2, 3, 4, 5}); 


New API for working with dates and times. If you don’t feel good old GregorianCallendar, you can try the new classes Clock, Time, LocalTime

  import java.time.LocalDate; import java.time.Period; ... LocalDate time = LocalDate.now(); Period period = Period.ofDays(2); LocalDate newDate = time.plus(period); System.out.println("year:"+newDate.getYear()); System.out.println("month:"+newDate.getMonth()); System.out.println("day:"+newDate.getDayOfMonth()); 

Source: https://habr.com/ru/post/203026/


All Articles