0

I'm trying to simplify the following code.

while(results.next())
    for(String column : colNames){
        if(EmptyUtil.isEmpty(results.getString(column))) {
            emptyCount++;
        }
    }
    
    if(emptyCount == colNames.size()){
        break;
    }
}

My main goal is to read a CSV file until an empty row and finish reading the file from there. And it's a necessity that I have to use this Csvjdbd driver ).

In the above code, results is a CsvResultSet (I've used Csvjdbc library to get this result set ). This CsvResultSet represents a single row in the CSV file inside the for loop. Basically I'm going through every row in the CSV file b colNames is the column headers list in the CSV. By using results.toString(column), I can get the value in the particular cell in the row.

If all the cells are empty in the row, I should break from the while loop.

The above code works as expected. I just need to know how to simplify that more.

Federico klez Culloca
  • 26,308
  • 17
  • 56
  • 95
Amila Fonseka
  • 392
  • 1
  • 5
  • 15
  • 2
    *If all the cells are empty in the row, I should break from the while loop.* - should not `emptyCount` be set back to zero for each row? – Scary Wombat Oct 14 '21 at 07:29
  • I haven't used this library, but since it is JDBC-styled, a couple of questions: (a) Is there is a primary key in a row? (b) if yes, can that be added to your `WHERE` clause, so that you don't have to make `null` checks and just go over the records fetched? – Sree Kumar Oct 14 '21 at 07:33
  • What solution did you choose? – gaborsch Oct 14 '21 at 11:51
  • 1
    @gaborsch all the below answers work. Thanks a lot for posting those answers. I chose a combination of your answer and Maurice Perry's answer. I liked your `allMatch` approach. It greatly reduces the processing time. – Amila Fonseka Oct 15 '21 at 00:06
  • @ScaryWombat yes that's right. I have missed putting here I think. Thanks for pointing that out. – Amila Fonseka Oct 15 '21 at 00:08

3 Answers3

2

Try this.

L: while(results.next()) {
    for(String column : colNames){
        if(!EmptyUtil.isEmpty(results.getString(column))) {
            continue L;
        }
    }
    // all the cells are empty in the row
    break;
}
1

I would use Stream API to decide, and an external variable instead of break.

boolean wasEmptyRow = false;
while (!wasEmptyRow && results.next()) {
    wasEmptyRow = colNames
        .stream()
        .map(column -> results.getString(column))
        .allMatch(EmptyUtil::isEmpty);
    if (! wasEmptyRow) {
        // process
    }
}

You simply create a stream from the column names, replace all values with the current value from the result, then check if all of them are empty. The allMatch is optimized, it will not check all columns if one failing case was found. This saves the break for you.

gaborsch
  • 15,408
  • 6
  • 37
  • 48
  • 1
    @gabrosch there's a catch on this approach though. results.getString method throws a CheckedException. Java's Stream API doesn't like CheckedExceptions much it seems :) I'm trying to find a proper way to handle this atm. – Amila Fonseka Oct 15 '21 at 01:23
  • @AmilaFonseka true, checked exceptions are the enemy in the streaming world :) You can use the block approach: `.map(column -> { try { return results.getString(column); } catch (WhateverException e) { log.error(ex); }})` – gaborsch Oct 15 '21 at 08:30
1

Not sure this is much simpler, but perhaps more readable:

while (results.next() && !allColumnsEmpty(results, colNames)) {
}

...

private boolean allColumsEmpty(ResultSet results, String...colNames) {
    for(String column : colNames){
        if(!EmptyUtil.isEmpty(results.getString(column))) {
            return false;
        }
    }
    return true;
}
Maurice Perry
  • 9,261
  • 2
  • 12
  • 24