UPDATE: I updated the answer to correct my misunderstanding of the question, as Tim pointed out in his comment.
As mentioned in my comment, I will assume that by "continue with the iteration" you mean just not to throw the exception and still return the results up until that point. I will also assume that you want to maintain the laziness of the Iterator.
If so, I would effectively decorate the java.util.Iterator to protect against their bug, but returning a Scala Iterator so that you still have the laziness that the original library should you need it. Something (non-prod-ready) on the line of:
def scalaIterator[A](it: java.util.Iterator[A]): Iterator[Option[A]] = new Iterator[Option[A]](){
private var hasBoomed: Boolean = false
override def hasNext = !hasBoomed && it.hasNext
override def next() = {
Try(it.next()) match {
case Failure(_) =>
hasBoomed = true
None
case Success(value) => Some(value)
}
}
}
Now, assuming you library call return Mailing instances, you should wrap it in Option:
val myFuntionalSequence: Iterator[Option[(String, String)]] = for{
mailingOpt <- scalaIterator(thirdPartyIterator)
} yield mailingOpt.map(mailing => (mailing.name, mailing.subject))
That will return a Iterator[Option[(String, Int)]].
Example results could be (when materialized):
Some(mailing1Pair),Some(mailing2Pair),None // in case of an exception
Some(mailing1Pair),Some(mailing2Pair),Some(mailing3Pair) // no exception
Now, what if you actually don't care about that final None? And what if all you actually want is a List[(String, Int)] that contains all the successfully returned Mailings? In that case, you would do:
val flattened: Iterator[(String, String)] = myFuntionalSequence.flatten
Now comes the really functional part ;)
But what if you actually want to know whether there was an exception? That is, you want to return None if there was at least one exception, or a Some(List(someMailing1Pair, etc....)) otherwise. Basically, what you want is a way to transform List[Option[(String, String)]] into an Option[List[(String, String)]].
Enter Traverse, from the Cats library:
implicit cats.implicits._
val myFuntionalSeuence: Iterator[Option[(String, String)]] = ...
val flipped: Option[List[(String, String)]] = myFuntionalSeuence.toList.sequence //notice the .toList here: we are materializing a lazy collection here
...at which point you treat it as any other Option. This approach is generic, it works with anything that implements Traverse and I recommend that you would read the docs I linked: you will find plenty of goodies! :)