Sat. Apr 20th, 2024

Continuing my Java Tips from experience that I have learned from code reviews to different programming tasks.

Tip 6: Don’t call .toString() on slf4j logging calls.

So if you’re following my other tips and using the formatting option of the logging messages like this:



list.parallelStream().filter(item -> !item.contains("BOB")).forEach(item -> logger.debug("Item: {} w/o Bob",item ));

That is great now what I have seen and so often overlooked is something like the following:

public void checkUrl(URL url) {
        if(url.getDefaultPort() != 80) {
           log.debug("URL ({}) not using standard port.", url.toString()); 
        }
    }

This code will work, it won’t give you any problems. However adding the url.toString(), means that code will be executed every time this line is hit, even if you have debug logging disabled. Many modern IDE’s will now warn on this but it’s important to call this out. slf4j logging will call the .toString() method to generate the string to insert into the logging, Instead write the code like this, and no extra processing is done:



public void checkUrl(URL url) {
        if(url.getDefaultPort() != 80) {
           log.debug("URL ({}) not using standard port.", url); 
        }
    }

Tip 7: Using parallelStream()

Java 8 introduced streams on collections. Honestly, probably the single biggest improvement to Java since its inception. the streams API provides parallelStream() this has proved itself to be extremely useful in data handling more times than I can count. However as good as it is, there are several drawbacks.

  • If your using Hibernate, then those threads will not have access to the EntityManager. So any model that did not eagerly load, will fail when trying to access.
  • Your limited to the size of the Common Thread Pool, which is shared.
  • Other objects used in the stream calls, must be final.

As I said parallelStream() can still be extremely useful. However, I advise you to work with a stream() and get every ounce of performance from it that you can, before trying parallelStream(). A standard stream() does not have the above drawbacks. Also in a testing environment, it’s very easy to have free threads in the Common Thread Pool, however, that is not always the case in a production system that will have considerable more load.

For additional information on parallelStream() and thread pools please see “When to Use a Parallel Stream in Java”

Tip 8: Reuse HTTPClients

Do not create a new HTTPClient for each and every request that you need to do from your code. Review and determine if you can use a single HTTPClient for all of your requests, or if you may need to create separate instances, maybe one per service/microservice you have that. However, from experience creating a new HTTPClient for every request will result in longer and longer times to create an instance.

Tip 9: List.of() v’s Arrays.asList()

Often I will see something like the following happen:

List<String> list = Arrays.asList("bob");

Now there is nothing wrong with this code, but when you generate a list from a single element, it is better to use:

List<String> list = List.of("bob");

The list generated from List.of() is more suited for performance and memory usage for single elements than Arrays.asList(). Use Arrays.asList() when having multiple elements, but List.of() for single elements.

List<String> list = Arrays.asList("bob","george","jim");

Arrays.asList() is your better option when you have more than 1 element.

Please see this Stackoverflow post for more information that really breaks down the differences.

Tip 10: Copy/Object Constructors

A copy constructor is a constructor for a Java class that takes a parameter of the same type as its only parameter to initialize a new object of the same type. This is used to duplicate objects quickly and easily while maintaining the code centralized for ease of access. A copy constructor would be something like the following:

class Person {
        private String lastName;
        private String firstName;

        public Person(String lastName, String firstName) {
            this.lastName = lastName;
            this.firstName = firstName;
        }
        
        public Person(Person person) {
            this.lastName = person.lastName;
            this.firstName = person.firstName
        }
    }

The second constructor takes an object of type Person and uses the field in it to initialize the new Person object. This is what a Copy Constructor does.

Now I would like to suggest an Object Constructor, yes I just made that name up as I know of no term that covers this. Now we have an object of a different type that contains data that we want to use to initialize the new object. Perhaps this is a DTO that takes an Entity object to initialize the DTO. Now let’s examine this code:

    class User {
        private String username;
        private String last;
        private String first;
        private String middle;
        private Date birthDate;

        public User(String username, String last, String first, String middle, Date birthDate) {
            this.username = username;
            this.last = last;
            this.first = first;
            this.middle = middle;
            this.birthDate = birthDate;
        }
    }
    
    class Person {
        private String lastName;
        private String firstName;

        public Person(String lastName, String firstName) {
            this.lastName = lastName;
            this.firstName = firstName;
        }

        public Person(Person person) {
            this.lastName = person.lastName;
            this.firstName = person.firstName
        }
        
        public Person(User user) {
            this.lastName = user.last;
            this.firstName = user.first;
        }
    }

Now the Person class has a constructor that takes a user, allowing it to initialize from a User object. Now as it is possible for a class to have any number of constructors as long as their signature is different, it is possible for a class to have a large number of possible constructors for initializing itself. This provides you with a single place to find the code for this conversion.

By Jeffery Miller

I am known for being able to quickly decipher difficult problems to assist development teams in producing a solution. I have been called upon to be the Team Lead for multiple large-scale projects. I have a keen interest in learning new technologies, always ready for a new challenge.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.