akuma8
akuma8

Reputation: 4691

Convert a foreach loop using stream

Need some helps to convert this loop using Stream API :

protected ResponseEntity<Object> handleMethodArgumentNotValid( MethodArgumentNotValidException ex,
        HttpHeaders headers, HttpStatus status, WebRequest request ) {

 Map<String, Set<String>> fieldErrorWithMessages = new HashMap<String, Set<String>>();
 List<FieldError> fieldErrors = ex.getBindingResult().getFieldErrors();
 Set<String> messages;
 for ( FieldError error : fieldErrors ) {
         String currentField = error.getField();
         String currentErrorMessage = message.getMessage( error.getCodes()[0], null, locale );
         if ( !fieldErrorWithMessages.containsKey( currentField ) ) {
              messages = new HashSet<String>();
              messages.add( currentErrorMessage );
              fieldErrorWithMessages.put( currentField, messages );
         } else {
             if ( !fieldErrorWithMessages.get( currentField ).contains( currentErrorMessage ) ) {
                fieldErrorWithMessages.get( currentField ).add( currentErrorMessage );
             }
         }
 }
.....
}

The goal is to group each field with its error messages. The error messages are stored in a message.properties file. This code works as expected but I would like to know if I can make it more concise using Stream API. Something like :

Map<String, Set<String>> fieldErrorWithMessages =fieldErrors.stream().collect( Collectors.groupingBy( FieldError::getField,/*something returnig a set of messages stored in messages.properties for each field*/ ) );

Note that to retrieve the message I use the first code of FieldError.getCodes(), see above : error.getCodes()[0]

Thanks

Upvotes: 3

Views: 567

Answers (2)

fps
fps

Reputation: 34460

This is a complement to @shmosel's answer. As it's been written there, the original code can be significantly improved before attempting to use streams. Here's a way:

protected ResponseEntity<Object> handleMethodArgumentNotValid(
        MethodArgumentNotValidException ex,
        HttpHeaders headers, 
        HttpStatus status, 
        WebRequest request) {

    Map<String, Set<String>> fieldErrorWithMessages = new HashMap<>();
    ex.getBindingResult().getFieldErrors().forEach(error -> 
        fieldErrorWithMessages.computeIfAbsent(
            error.getField(),
            k -> new HashSet<>())
        .add(message.getMessage(error.getCodes()[0], null, locale)));

    // .....
}

Upvotes: 0

shmosel
shmosel

Reputation: 50716

There's actually significant room to cut that down without streams, but I'll cut to the chase:

Map<String, Set<String>> fieldErrorWithMessages = ex.getBindingResult()
        .getFieldErrors()
        .stream()
        .collect(Collectors.groupingBy(
                FieldError::getField,
                Collectors.mapping(
                        error -> message.getMessage(error.getCodes()[0], null, locale),
                        Collectors.toSet())));

Upvotes: 4

Related Questions