How to create a customisation annotation for splitting request param and collect return result?

Ben Luk :

I have a method params is a list which is lager than 50000 items; Limited to the business logic, the list must less than 30000, so that I have a method to split this array to 2d array before the logic

public static final <T> Collection<List<T>> partitionBasedOnSize(List<T> inputList, int size) {
        AtomicInteger counter = new AtomicInteger(0);
        return inputList.stream().collect(Collectors.groupingBy(s -> counter.getAndIncrement() / size)).values();
}

This is my current solution:

public List<Account> getChildrenList(List<Long> ids) {
        List<Account> childrenList = new ArrayList<>();
        Collection<List<Long>> childrenId2dList = PartitionArray.partitionBasedOnSize(childrenIdsList, 30000);
        for (List<Long> list : childrenId2dList) {
            //this is my business logic: start
            childrenList.addAll(accountRepository.getAccounts(list));
            //this is my business logic: end
        }
        return childrenAccountsList;
}

I would like to create an annotation on top of the method instead of many duplicate code(check and spite each time...)

Sorry for my bad english, I have draw a diagram: method called>spite array>business logic>collect all result>return enter image description here

Benoit :

In my opinion using annotations is a bit of over-engineering (You have to write an annotation processor) in this case. You could easily use generics and lambdas and/or method references to reach your goal. For instance:

Update PartitionArray this way:

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

public class PartitionArray {

    private static <T> Collection<List<T>> partitionBasedOnSize(List<T> inputList, int partitionSize) {
        Collection<List<T>> collection = new ArrayList<>();
        int remainingSize = inputList.size();
        int index = 0;
        while (remainingSize > partitionSize) {
            collection.add(inputList.subList(index, index + partitionSize));
            remainingSize -= partitionSize;
            index += partitionSize;
        }
        collection.add(inputList.subList(index, index + remainingSize));
        return collection;
    }

    public static <D, T> List<D> partitionAndDoBusinessFunction(List<T> ids, Function<List<T>, List<D>> businessFunction, int partitionSize) {
        List<D> dataList = new ArrayList<>();
        Collection<List<T>> idListCollection = partitionBasedOnSize(ids, partitionSize);
        for (List<T> idList : idListCollection) {
            dataList.addAll(businessFunction.apply(idList));
        }
        return dataList;
    }
}

Then simply use it from your AccountService (using method reference):

import java.util.List;

public class AccountService {

    private AccountRepository accountRepository;

    public List<Account> getAccounts(List<Long> ids) {
        return PartitionArray.partitionAndDoBusinessFunction(ids, accountRepository::getAccounts, 30000);
    }
}

Or using lambdas:

import java.util.List;

public class AccountService {

    private AccountRepository accountRepository;

    public List<Account> getAccounts(List<Long> ids) {
        return PartitionArray.partitionAndDoBusinessFunction(ids, idList -> {
            List<Account> accounts = accountRepository.getAccounts(idList);
            // do more business on accounts
            return accounts;
        }, 30000);
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=36766&siteId=1