Java 8 vivid expression with sequence

In our web application project, we use Redis to manage the session. To support it, we serialize any object that will be stored in the session.

For example, we use DTO to store the beans that are used to display on the screen. Even if the DTO has any other object inside (Composition), we must also serialize it otherwise, we will get a NotSerializableException .

I had a problem when I was creating an anonymous inner class to implement Comparator , as shown below:

 Collections.sort(people, new Comparator<Person>() { public int compare(Person p1, Person p2) { return p1.getLastName().compareTo(p2.getLastName()); } }); 

The above code threw a NotSerializableException , and I resolved it by creating a class that implements the Comparator interface as well as Serializable . The problem was that it was thrown onto the JSP page that used this DTO. I had to do a lot of debugging to find the actual problem.

But now I'm interested in changing the above code to use a Lambda expression, as shown below:

 Collections.sort(people, (p1, p2) -> p1.getLastName().compareTo(p2.getLastName())); 

However, I fear that the same exception will occur. Is a Lambda expression an internal object of an object?

+5
source share
4 answers

You can create a serializable lambda expression via

 Collections.sort(people, (Comparator<Person>&Serializable) (p1, p2) -> p1.getLastName().compareTo(p2.getLastName())); 

but it should be noted that creating Comparator through

 (p1, p2) -> p1.getLastName().compareTo(p2.getLastName()) 

carries discouraged redundancy. You call getLastName() twice, and you will need to call it in the right parameter variable anyway. More straightforward to use

 Comparator.comparing(Person::getLastName) 

instead of this. You can also make this comparator serializable, although this implies losing most of the brevity:

 Collections.sort(people, Comparator.comparing((Function<Person,String>&Serializable)Person::getLastName)); 

It is also more stable. The serialized form of the lambda expression contains a reference to the implementation method, which in the first embodiment is a synthetic method with a name generated by the compiler, which can change when using another lambda expression in the definition method. In contrast, Person::getLastName points to the named getLastName method as an implementation method (at least with javac ).

But as a rule, serializable lambda expressions can contain amazing compiler dependencies and should be used with caution.

Since they are intended to describe behavior, not data, in any case, their long-term storage does not make sense. To transfer them between JVMs with the same code base, they are sufficient.

+3
source

lambda

Yes, it creates an object. The second parameter is of type Comparator, so that will be created implicitly.

See this: Does the lambda expression create an object on the heap every time it is executed?


Built-in Redis

On the other hand, it will be useful if your application runs locally. To start the embedded Redis server, you can see my personal project on github: https://github.com/alexbt/sample-spring-boot-data-redis-embedded .

It uses the following dependencies:

 <dependency> <groupId>com.github.kstyrc</groupId> <artifactId>embedded-redis</artifactId> <version>0.6</version> </dependency> 

and basically these 3 lines to process:

 new RedisServer(redisPort); redisServer.start(); redisServer.stop(); 

You can even do this in a side project, just to stop / start Redis on a specific port. It would be even better if you integrated it inside the trigger of the application with a specific Spring profile, but in the near future it will be more.


Library website: https://github.com/kstyrc/embedded-redis :

Starting RedisServer is as simple as:

 RedisServer redisServer = new RedisServer(6379); redisServer.start(); // do some work redisServer.stop(); 
+1
source

If you want to switch to another serialization structure, for example Kryo , you can get rid of many restrictions or requirements, the implemented interface must implement Serializable . In addition, you will not need to implement all your serialized Serializable classes, as a rule, they have much more options for setting serialization, the serialized form is likely to be smaller (memory storage), and all this will most likely be faster.

The approach to lambda serialization is to

  • Modify InnerClassLambdaMetafactory to always generate the code needed for serialization
  • Directly call LambdaMetaFactory during deserialization

For more details and code see this blog post

0
source

If you want to switch to another serialization structure, for example, Kryo, you can get rid of the multiple restrictions or requirements by which the implemented interface must implement Serializable. In addition, you do not need all of your serialized classes to implement Serializable, as a rule, have much more options for setting serialization, the serialized form is likely to be smaller (memory storage), and all this is likely to be faster.

The approach to lambda serialization is to

Modify InnerClassLambdaMetafactory to always generate the code needed for serialization Directly call LambdaMetaFactory during deserialization

-1
source

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


All Articles