Home > database >  How do I continue with next element in the Java Stream in case of exception?
How do I continue with next element in the Java Stream in case of exception?

Time:10-26

I have a stream like this,

List<String> test = Arrays.asList("1", "2,", "3");

test.stream().map(t -> {
  try {
    validate(t);
  } catch (Exception e) {
    throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage(), e);
  }

  return true;
})

In case of an exception, I would like to store it somewhere, process the next element and then show all exceptions at once. Is this possible?

CodePudding user response:

Well, don't rethrow the exception:

var exceptions = test.stream().map(t -> {
    try {
      validate(t);
    } catch (Exception e) {
      return e;
    }

    return null;
  })
    .filter(Objects::nonNull) // if you don't need to preserve the index
    .toList();

CodePudding user response:

I modified your code slightly. Your main issue is that you're re-throwing that exception when you catch it -- that will stop processing at the first exception. Then you need some way to store the inputs that cause an error (that's what invalidInputs is for. I'm assuming that your next step is to actually use the results of that input to convert, otherwise you don't need to use map(), so my "validate" method also just does the conversion too. I use a JUnit test harness for stuff like this, and I left in the assert()s; you should take them (and the @Test annotation) out for your code.

    //throws NumberFormatException if input doesn't parse into an integer
public static Integer validate(String input) throws Exception{
    return Integer.parseInt(input);
}

@Test 
public void testStreamMap() {
    List<String> test = Arrays.asList("1", "2,", "3");
    List<String> invalidInputs = new ArrayList<>();
    List<Integer> result= test.stream().map(t -> {
        Integer localResult;
      try {
        localResult=validate(t);
      } catch (Exception e) {
        invalidInputs.add(t);
        localResult=null;
      }
      return localResult;
    }).collect(Collectors.toList());
    assertTrue(invalidInputs.contains("2,"));
    assertFalse(result.contains(2));
}

CodePudding user response:

You can try this approach to collect all the exceptions in a list as follows:

Here,

I have iterated over the list using forEach and in case of catch , added the exception e in the listOfExceptions list.

  • As I have entered three invalid inputs in the list , it is giving three exceptions in the list at the end corresponding to each element which is giving exception.
  • For the demo purpose, I have created one more list listOfElementsWithoutExceptions showing the elements which are processed without any exceptions.

Note: You can have your own custom exception list in place of List<Exception>.

public class Test2 {
    public static void main(String[] args) {
        List<String> test = Arrays.asList("test1", "test2", "3","4","test5","6");

        List<Exception> listOfExceptions = new ArrayList<>();
        List<String> listOfElementsWithoutExceptions = new ArrayList<>();
        test.forEach(t -> {
            try {
                validate(t);
                listOfElementsWithoutExceptions.add(t);
            } catch (Exception e) {
                listOfExceptions.add(e);
            }
        });
        System.out.println("list of exceptions:: "   listOfExceptions);
        System.out.println("list of elements without exceptions:: "  listOfElementsWithoutExceptions);
    }

    private static void validate(String t) {
        Integer.parseInt(t);
    }
}

Output:

list of exceptions::

[java.lang.NumberFormatException: For input string: "test1", 
java.lang.NumberFormatException: For input string: "test2", 
java.lang.NumberFormatException: For input string: "test5"]

list of elements without exceptions:: [3, 4, 6]
  • Related