简体   繁体   中英

java compare multiple values and find best match

I need to find best matched employee salary in the DB records as:

Name:   City:     State:

A       (null)    (null)

A       (null)    DEL

(null)  (null)    (null)

A        SAKET    DEL

Match order should be:

1. NAME = name, STATE = state, CITY = city

2. NAME = name, STATE = state , CITY = NULL

3. NAME = name, STATE = NULL, CITY = NULL

4. NAME = NULL, STATE = NULL, CITY = NULL

Means if in a row where all attributes matches – it should be selected, if we do not have that kind of data we should go to next best option like select state and city as NULL, etc.

My code as below, is giving me correct results but I need a more efficient way.

    private static BigDecimal getsalaryForBestMatch(ResultSet results, EmployeeRq request) throws Exception{
    BigDecimal salary = null;
    BigDecimal salaryWithState = null;
    BigDecimal salaryWithName = null;
    BigDecimal salaryWithNoMatch = null;
     while (results.next()) {

        String billerName = results.getString("EMP_NAME") != null ? results.getString("EMP_NAME").trim() : null;
        String city = results.getString("CITY") != null ? results.getString("CITY").trim() : null;
        String state = results.getString("STATE") != null ? results.getString("STATE").trim() : null;

        BigDecimal salaryRslt = null;

        if(results.getString("SALARY") != null){
            salaryRslt = BigDecimal.valueOf(results.getDouble("SALARY"));               
        }  
        if(billerName != null && !billerName.equals("") && billerName.equals(request.getBillPaymentsalaryCalculateInfo().getBillerName())){
            if(city != null && !city.equals("") && city.equals(request.getMsgRqHdr().getCity()) &&
                    state != null && !state.equals("") && state.equalsIgnoreCase(request.getMsgRqHdr().getstate())){
                salary = salaryRslt;
                break;
            } else if((city == null || city.equals("")) && state != null && !state.equals("") &&
                    state.equalsIgnoreCase(request.getMsgRqHdr().getState())){
                salaryWithState = salaryRslt;                   
            } else if((city == null || city.equals("")) && (state == null || state.equals(""))){
                salaryWithName = salaryRslt;                    
            }
        } else if((billerName == null || billerName.equals("")) && (city == null || city.equals("")) && 
                (state == null || state.equals(""))){
            salaryWithNoMatch = salaryRslt;             
        }
     }

     if(salary != null){
         return salary;
     } else if(salaryWithState != null){
         salary = salaryWithState;
     } else if(salaryWithName != null){
         salary = salaryWithName;
     } else if(salaryWithNoMatch != null){
         salary = salaryWithNoMatch;
     } 

     return salary;

}

EDIT : I dont want to use 3 extra variables: salaryWithState, salaryWithName, salaryWithNoMatch.

I want just to give the general idea how this can be implemented, so I haven't actually tested and checked if it will give you the right salary.

public BigDecimal getSalaryForBestMatch(ResultSet resultSet, PaymentSalaryInfo paymentSalaryInfo) {
    Map<String, Supplier<String>> m1 = new HashMap<>();
    m1.put("EMP_NAME", paymentSalaryInfo::getBillerName);
    m1.put("STATE", paymentSalaryInfo::getState);
    m1.put("CITY", paymentSalaryInfo::getCity);

    Map<String, Supplier<String>> m2 = new HashMap<>();
    m2.put("STATE", paymentSalaryInfo::getState);
    m2.put("CITY", paymentSalaryInfo::getCity);

    Map<String, Supplier<String>> m3 = new HashMap<>();
    m3.put("CITY", paymentSalaryInfo::getCity);


    Optional<String> salary = Optional.empty();

    while(resultSet.next() && !salary.isPresent()) {
        salary = apply(m1, resultSet);
        //check salary and then apply(m2, resultSet) ....
    }

    return salary.isPresent() ? new BigDecimal(salary.get()) : null;
}


public Optional<String> apply(Map<String, Supplier<String>> filter, ResultSet resultSet) {
    boolean allMatch = filter.entrySet().stream().allMatch(entry -> {
        String value = resultSet.getString(entry.getKey());

        return value != null && value.equals(entry.getValue().get());
    });

    return allMatch ? Optional.of(resultSet.getString("salary")) : Optional.empty();
}

I have written the same logic in a different way with using arrays. If your environment can afford to use arrays, you can use this code. But I have not tested the code.

 private static BigDecimal getsalaryForBestMatch(ResultSet results, EmployeeRq request) throws Exception{
    BigDecimal salary = null;
    int matchCount = 0;
    String rBillerName = request.getBillPaymentsalaryCalculateInfo().getBillerName();
    String rCity = request.getMsgRqHdr().getCity();
    String rState = request.getMsgRqHdr().getstate();

    String [] truthArray = new String[] {rBillerName, rCity, rState};

    while (results.next()) {
        String billerName = results.getString("EMP_NAME") != null ? results.getString("EMP_NAME").trim() : null;
        String city = results.getString("CITY") != null ? results.getString("CITY").trim() : null;
        String state = results.getString("STATE") != null ? results.getString("STATE").trim() : null;
        BigDecimal salaryRslt = results.getString("SALARY") != null ? BigDecimal.valueOf(results.getDouble("SALARY")): null;

        String [] testArray = new String[] {billerName, city, state};

        int localMatchCount = 0;
        for(int i = 0; i < testArray.length; i++) {
            if(testArray[i] != null && testArray[i].equals(truthArray[i]))
                localMatchCount++;
            else {
                break;
            }
        }

        if(localMatchCount >= matchCount){
            matchCount = localMatchCount;
            salary = salaryRslt;
        }
    }
    return salary;
}

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