views:

138

answers:

3

I have to translate the following code from Java to Scala:

EDIT: added if-statements in the source (forgot them in first version)

for (Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator(); i.hasNext();) 
{
  if (someCondition) {
    ExceptionQueuedEvent event = i.next();
    try {
      //do something
    } finally {
      i.remove();
    }
  }
}

I'm using the JavaConversions library to wrap the Iterable. But as i'm not using the original Iterator, i don't know how to remove the current element correctly from the collection the same way as i did in Java:

import scala.collection.JavaConversions._
(...)
for (val event <- events) {
  if (someCondition) {
    try {
      // do something
    } finally {
      // how can i remove the current event from events?
      // the underlying type of events is java.lang.Iterable[javax.faces.event.ExceptionQueuedEvent]
    } 
  }
}

Can someone help me? I guess it's easy, but i'm still kinda new to Scala and don't understand what's going on when Scala wraps something of Java.

A: 

When you use JavaConversions to wrap Java collections, you just get an object that adapts the Java collection to the appropriate Scala trait (interface). In Java, you might see the same thing (for example, you could imagine a adapter class that implements the Iterator interface and wraps an Enumeration.) The only difference is that in Scala you can add the 'implicit' modifier to a declaration to tell the compiler to automatically insert calls to that method if it will make the code compile.

As for your specific use case, Iterators in Scala intentionally omit the remove() method for a number of reasons. The conversion from scala.collection.Iterator to java.util.Iterator promises to unwrap a j.u.Iterator if possible, so I suppose you could rely on that to access the remove() method. However, if you are iterating over the entire collection and removing everything, why not just do your work in a foreach loop and then clear the collection or replace it with an empty one after you finish?

David Winslow
just edited my code, i forgot the if-statements - so i'm not removing everything from the collection. At the end of it, the Java Iterable (with some elements removed) must still exist (framework code relies on it). Thanks for your thoughts. Until now, every try to realize the removal failed. Will try a bit more around...
ifischer
A: 

Does this suggest how do accomplish what you want?

scala> val l1 = List("How", "do", "I", "love", "you")
l1: List[java.lang.String] = List(How, do, I, love, you)

scala> val evens = for ( w <- l1; if w.length % 2 == 0 ) yield { printf("even: %s%n", w); w }
even: do
even: love
evens: List[java.lang.String] = List(do, love)

Basically, you get your Scala Iterable or Iterator using the appropriate implicit conversion from JavaConversions, use a for comprehension that includes the condition on which elements you want to process and collect the results. Use exception handling as necessary.

Randall Schulz
A: 

Thanks for all the help. So i had to do without using JavaConversions. But it still looks nice&scalafied ;)**

This is my final code, which seems to work:

val eventsIterator = events.iterator    
for (eventsIterator.hasNext) {
  if (someCondition) {
    try {
      // do something
    } finally {
      eventsIterator.remove
    } 
  }
}
ifischer