The Application of lambda expressions in Java 8 and some generics, java8lambda

Source: Internet
Author: User

The Application of lambda expressions in Java 8 and some generics, java8lambda

The syntax part will not be written. We will directly throw a practical problem to see what convenience these new features of Java 8 can bring to us.

Some generic programming is used to simplify the code.

Scenario:

A Data class used to record employee information

public class Employee {        public String name;    public int age;    public char sex;    public String time;    public int salary;}

We have a column of such data

List<Employee> data = Arrays.asList(e1,e2,e3......)

Now, you need to group Employee by the first letter of the Employee's name (assuming all are English names:

The result is a ing relationship such as Map: char-> List <Employee>.

public static Map<Character, List<Employee>> groupByFirstChar(    List<Employee> data){        Map<Character, List<Employee>> result = new HashMap<>();        for(Employee e : data){            Character c = e.name.charAt(0);            List<Employee> l = result.get(c);            if(l == null){                l = new ArrayList<>();                result.put(c, l);            }            l.add(e);        }        return result;}

The code is not complex and can be completed quickly. The boss sees that you are so efficient. So, divide the work into groups based on the salary, which is less than 5000, 5000 ~ 10000 of... and so on

It won't be too difficult. Just change the key and perform logic processing.

Public static Map <String, List <Employee> groupBySalary (List <Employee> data) {Map <String, List <Employee> result = new HashMap <> (); for (Employee e: data) {String key = separate (e. salary); List <Employee> l = result. get (key); if (l = null) {l = new ArrayList <> (); result. put (key, l);} l. add (e);} return result;
} Private static String separate (int salary) {if (salary <= 5000) {return "less than 5000";} if (salary <= 10000) {return "5000 ~ 10000 ";} if (salary <= 20000) {return" 10000 ~ 20000 ";} return" 20000 or above "}

Then the boss said, divide the group according to the employee's employment year...

The code will not be written here. We can find that no matter how grouping, the only change is the key value selection method,

For the first time, use the first letter of the Employee name as the key:

Employee e -> e.name.charAt(0)

The second time, the salary of the Employee is converted to String by using the separat method as the key:

Employee e -> separate(e.salary):String

And so on

Employee e -> getYear(e.time):String

In fact, for the first time, you can write the first letter as a method.

Employee e -> getFirstChar(e.name):Character

To make it look more beautiful, we can say that the parameters of the three methods are set to the Employee method body and will not be written here. Only the parameters and returned values are listed here.

Employee e -> getFirstChar(e) : CharacterEmployee e -> separate(e) : StringEmployee e -> getYear(e) : String

-> Parameter on the left, return value on the right, and method signature on the right.

Then we will naturally think of extracting the changed part as a parameter, and the other unchanged parts as a method body, then we can save the repeated code. The obviously changed part is listed above, the method for converting Employee e into key, but we know that java cannot pass methods as parameters. However, this is not a problem for a slightly experienced programmer. We can use interfaces to achieve our goal and encounter another problem. The return values of the above three methods are different, so we need to use generic:

public static <K> Map<K, List<Employee>> groupByKey(List<Employee> data, GetKey<K> getKey){    Map<K, List<Employee>> result = new HashMap<>();    for(Employee e : data) {        K key = getKey.getKey(e);        List<Employee> l = result.get(key);        if (l == null) {            l = new ArrayList<>();            result.put(key, l);        }        l.add(e);    }        return result;}
interface GetKey<K>{
K getKey(Employee e);
}

The first requirement above can be implemented in this way

Map<Character, List<Employee>> result = groupByKey(data, new GetKey<Character>() {            @Override            public Character getKey(Employee e) {                e.name.charAt(0);            }        });

Second Requirement

Map<String, List<Employee>> result = groupByKey(list, new GetKey<String>() {            @Override            public String getKey(Employee e) {                separate(e.salary);            }        });

We can find that we only need to change the implementation of generic parameters and anonymous internal classes. The only problem is that it is not very nice to write, and there are a lot of routine code, especially in anonymous internal classes.

In fact, we only care about the parameters and return values of this anonymous internal class. The other part is only the syntax requirement.

Java 8 just provides us with a good way to avoid complicated routine: lambda expressions, the above implementation can be written

Map<Character, List<Employee>> resultByFirstChar = groupByKey(list, e -> e.name.charAt(0));Map<String, List<Employee>> resultBySalary = groupByKey(list, e -> separate(e.salary));

Lambda expressions only show what we care about, parameters and return values. Due to type inference, you can save the parameter type. The specific syntax is not described here. You can find a lot of information online.



Extra:

If you have a good understanding of generics, The groupByKey method can be further abstracted:

public static <K, E> Map<K, List<E>> groupBy(List<? extends E> data, Function<? super E, ? extends K> fun) {    Map<K, List<E>> result = new HashMap<>();    for(E e : data) {        K k = fun.apply(e);
List<E> l = result.get(k); if(l == null) { l = new ArrayList<>(); result.put(k, l); } l.add(e); } return result;
}

We have also extracted the Employee class, and the benefits are obvious.

The Function interface is a newly added Java 8 interface:

@FunctionalInterfacepublic interface Function<T, R> {    R apply(T t);}

Input a T type and return the R type. The combination of generic and functional programming is very good. Although the new features of Java 8 are all spams, the benefits are always good, which gives us more choices.

 

If you have time, we will introduce stream, another Java 8 provisioner.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.