简体   繁体   中英

How to make it more generic this for loop with generics?

These are classes of my project. The class Bean is a super type of Employe and Computer and not is intanziable.

abstract Class Bean{
   private HashMap<String, String> fields = null;
   protected Bean(Map<String, Object> row) {
        //fill HashMap fields
   }
}
public class Employe extends Bean {
    public Employe (Map<String, Object> row) {
        super(row);
   }
}

public class Computer extends Bean {
    public Computer (Map<String, Object> row) {
        super(row);
    }
}

How to make it more generic this for loop with generics ?

I would write the two cycles below once using generics in a utility method riusable.

//Loop 1

List<Map<String, Object>> employeRows = //from query on database

List<Employe> employList = new ArrayList<Employe>();

for (Map<String, Object> row : employeRows) {
    Employe e = new Employe(row);
    employList .add(e);
}

//Loop 2

List<Map<String, Object>> computerRows = //from query on database

List<Computer> computerList = new ArrayList<Computer>();

for (Map<String, Object> row : computerRows ) {
    Computer c = new Computer(row);
    computerList.add(c);
}

This pseudo-code is an example of what I want to achieve:

List<Employe> = Utility.toList(employeRows, ...);
List<Computer> = Utility.toList(computerList, ...);

If you're using Java 7 or below, factory pattern is the way to go. But if you're already on Java 8, you can achieve this with streams and lambda / method reference.

Here's how you do it with Java 8:

public static <T> List<T> toList(List<Map<String, Object>> rows, Function<Map<String, Object>, T> mapper) {
    return rows.stream().map(mapper).collect(Collectors.toList());
}

And then call this method by passing the constructor as method reference:

List<Map<String, Object>> employeRows = new ArrayList<Map<String, Object>>();
List<Map<String, Object>> computerRows = new ArrayList<Map<String, Object>>();

List<Employe> employList = toList(employeRows, Employe::new);
List<Computer> computerList = toList(computerRows, Computer::new);

Use a Factory Pattern, one abstract factory

interface ObjectCreater<T> {
  T create(Map<String, Object> row);
}

and two Implementations, eg for Employee

class EmployeeCreater implements ObjectCreator<T> {
  T create(Map<String, Object> row) {
     return new Employee(row); // or the constructor logic inlined
  }
}

define a method (= Utility.toList()):

List<T> toList(List<Map<String, Object>> row, ObjectCreator<T> creator) {
  // the upper loop using the factory instead of the Constructor
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM