5 Ways to boost your code up using functional programming Style in Java
Tags: java, tutorial, beginners
Published: 2020-04-24 02:07:09

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/rmjdbdnmc4cxbhiesj4s.png)

The release of Java 8 on March, 2014 brought up a bunch of significant changes to the java world and and among the most important are `Streams` and Functional Programming.

The newer versions of java reinforced its use by adding quite useful new functionalities.

So today we'll turn java 7 and earlier code into Java 8+ Using Functional Style Programming.

###1- Sort a Pets list using a non natural Order.

Prior java 8

```java
        List<Pet> pets = new ArrayList<>();
        pets.add(new Pet("Scoby", 10));
        pets.add(new Pet("Jahnna", 12));
        pets.add(new Pet("Kira", 15));
        pets.add(new Pet("Snoopy", 2));
        pets.add(new Pet("Jeck" ,7));
        
        Collections.sort(pets, new Comparator<>() {
            @Override
            public int compare(Pet pet1, Pet pet2) {
                return (int) (pet1.getWeight() - pet2.getWeight());
            }
        });
        
       for(Pet pet : pets) {
            System.out.println(pet.getName());
       }
```

Using Lambda and Streams Approach.

```java
        List<Pet> pets = new ArrayList<>();
        pets.add(new Pet("Scoby", 10));
        pets.add(new Pet("Jahnna", 12));
        pets.add(new Pet("Kira", 15));
        pets.add(new Pet("Snoopy", 2));
        pets.add(new Pet("Jeck" ,7));
        
        pets.stream()
                .sorted((p1, p2) -> (int) (p1.getWeight() - p2.getWeight()))
                .forEach(Pet::getName);
```

In the first example we had to provide a anonymous class that extends from `Comparator` and override the abstract behavior. Then pass it as a parameter to the `Collections.sort` method, because Pet class does not implement `Comparable` interface.

Using Java 8+, let's create a more descriptive code that expresses a what regardless of how.

###2- Turn our pretty pets into wilds.

Java 7 or earlier.
```java
        // pets List       

        List<WildAnimal> wild = new ArrayList<>();
        for(Pet p : pets) {
            WildAnimal animal = new WildAnimal(p.getName(), p.getWeight() * 2);
            wild.add(animal);
            
            animal.hunt();
        }
```
Using Java 8 Features.

```java
      // pets List
        pets.stream()
                .map(e -> new WildAnimal(e.getName(), e.getWeight() * 2))
                .forEach(WildAnimal::hunt);
```

Now we are using the `map()` method to convert one type into another, in this case our tiny pets are now ruthless wild animals, and at the end for each of them we call `hunt()`.

So far our 2 first examples were too Simple, let's fire some more interesting ones.

### 3- Calculate statistics from Jobs Applicants

Maybe you are working at home because of quarantine (or you've been working remote along before) and were asked for calculate some statistics given and countless list of job applicants. only taking who match the qualification criteria and theirs ages are between 20 and 35 years (just an example we don't want to be that exclusives). to make some business logic.

Let's see how can we do that using the old way.

```java
        // applicants list ...
        int count = 0;
        int totalQualification = 0;
        double avgQualification;

        for (Applicant applicant : applicants) {
            if ((applicant.getAge() > 19 && applicant.getAge() < 36)
                    && applicant.getInterviewQualification() > 69) {
                count++;
                totalQualification += applicant.getInterviewQualification();
            }
        }

        avgQualification = count != 0 ? totalQualification / count : 0;
        System.out.format("Qualification stats {count=%d, total=%d, avg=%f}",
                count, totalQualification, avgQualification);
```

Well not bad, but we can do better using java 9+
```java
        // applicants list ...
        var stats = applicants.stream()
                .filter(a -> a.getAge() > 19 && a.getAge() < 36)
                .filter(a -> a.getInterviewQualification() > 6)
                .mapToInt(Applicant::getInterviewQualification)
                .summaryStatistics();
        
        System.out.format("Qualification stats {count=%d, total=%d, avg=%f}",
                stats.getCount(), stats.getSum(), stats.getAverage());
```

Note: How we chain operations as if it were a pipeline, because in fact this is a pipeline.


###4 - Group applicants by the position they applied.

Before
```java
        Map<Position, List<Applicant>> group = new HashMap<>(); 
        for(Applicant ap: applicants) {
            List<Applicant> list = group.get(ap.getPosition());
            if(list == null){
                list = new ArrayList<>();
                group.put(ap.getPosition(), list);
            }
            list.add(ap);
        }
        System.out.println(group);  
```

After
```java
        Map<Position, List<Applicant>> group = applicants
                .stream()
                .collect(Collectors.groupingBy(Applicant::getPosition));
        
        System.out.println(group);
```

The code looks much clearer in the second example, in this case we use the `groupingBy` collector which takes a Function as a parameter in this case` Function <Applicant> `. The method reference allows us to run the `getPosition` method from the current applicant being passed and use the return value as a group.

Our last example is going to use Dates.

###5 - Grouping the last 7 days of statistical analysis about COVID-19
because you are bored and want to build another app to visualize Corona-virus statistics maybe this example could help.


Using the old way

```java
        List<Summary> lastWeek = new ArrayList<>();
        
        Calendar calendar = GregorianCalendar.getInstance();
        calendar.setTime(new Date());
        
        for(int i = 0; i < 7; i++) {
            Date current = calendar.getTime();
            lastWeek.add(covid19DataSource.getSummaryByDate(current));
            calendar.add(Calendar.DAY_OF_MONTH, -1);
        }
        
        System.out.println(lastWeek);
```

Using Java 9+

```java
        LocalDate today = LocalDate.now().plusDays(1);
        
        List<Summary> lastWeek = today.minusDays(7).datesUntil(today, Period.ofDays(1))
                .map(covid19DataSource::getSummaryByDate)
                .collect(Collectors.toList());
        
                System.out.println(lastWeek);
```

Here we are not only using lambda and Stream but also are using newer Java's time API. The `datesUntil` method was added in Java 9 allow us to get a Stream of `LocalDate` objects which we map to get the corresponding covid 19 summary and then just collect it into a list.

```
[Summary{confirmed=0, recovered=0, deaths=0, date=2020-04-17}, ...
```

Both approaches return this same result, it'd be cool getting the same metrics in real life. :D


Thanks for reading, Keep safe :).