Use Java Stream features - if multiple statements to be executed within the loop

89 Views Asked by At

How to Use Java Stream features - if multiple statements to be executed within the loop: The code snippet:

PDAcroForm pdAcroForm = pdfDocument.getDocumentCatalog().getAcroForm();
JSONObject jsonData = new JSONObject(pdfdata);

String[] specialChars = {" ", "-", ".", "(", ")", "/", "*"};
String[] specialCharsReplaceWith = {"_", "_1_", "_2_", "_3_", "_4_", "_5_", "_6_"};

for (PDField pdField : pdAcroForm.getFields()) {
    
    String fieldName = pdField.getFullyQualifiedName();
    System.out.println("fieldName:" + fieldName);

    for(int i = 0; i < specialChars.length; i++) {
        fieldName = fieldName.trim().replace(specialChars[i], specialCharsReplaceWith[i]);
    }

    if(StringUtils.isNotEmpty(fieldName)) {
        fieldName = fieldName.substring(0, 1).toLowerCase().concat(fieldName.substring(1));
    }

    if (jsonData.has(fieldName)) {
        String value = jsonData.getString(fieldName);
        pdField.setValue(value);
        pdField.setReadOnly(true);
    }
}

any suggestions?

1

There are 1 best solutions below

0
daniu On BEST ANSWER

Yes, since you need both the PDFField and the resulting json field name in the end, a Stream does not seem appropriate. I would make it look something like

pdAcroForm.getFields().forEach(pdField -> {
 Optional.of(jsonFieldMapper.getFieldName(pdField))
   .filter(jsonData::has)
   .map(jsonData::getString)
   .ifPresent(jsonValue -> {
     pdField.setValue(jsonValue);
     pdField.setReadOnly(true);
   });
});

and extract the whole replacement and substringing into the jsonFieldMapper.

EDIT: I just realized that your question is just as much about "the whole replacement", so how can we make that into a Stream?

Each of the individual replacements are a Function<String, String>, and we can fold them into a single one using a Stream by

Stream<Function<String, String>> replacements = Stream.of(
  s -> s.replace(" ", "_"),
  s -> s.replace("-", "_1_")
  //, ...
);
Function<String, String> replaceAll = replacements.reduce(UnaryOperator.identity(), (r1, r2) -> r1.andThen(r2));

which you could then use as String replaced = replaceAll.apply(pdField.getFullyQualifiedName()).

I'd argue it's not more readable than just going with a for loop:

String fieldName = pdField.getFullyQualifiedName();
for (Replacement r : List.of(
 replacement(" ", "_"),
 replacement("-", "-1"),...) {
 fieldName = r.apply(fieldName);
}
// with
UnaryOperator<String> replacement(String replace, String with) {
 String replaceIn -> replaceIn.replace(with);
}

Side Note: I'd guess you need a replaceAll though.