tags:

views:

124

answers:

9

In Java, I want to go through a list of elements and insert a new one at the right place. I was thinking of doing it in this way:

for( Tab tab : tabList )
  if( newTab.getPriority() < tab.getPriority() ) {
    newTab.insertBefore(tab);
    break;
  }
if( tab == null )
  newTab.insertBefore(endMarker);

Unfortunately, tab is not accessible outside the for loop. Is there any simple way to do what I want or do I have to use a boolean?

A: 

tab is scoped to the body of the for loop, if I remember my Java correctly (and if it works the way one would "expect", i.e. how for scoping works in C99 and C++), so this probably doesn't compile.

Jeff Walden
+2  A: 

You can't access a foreach iterator variable outside of the loop since it goes out of scope. As you wrote it, the above code doesn't compile.

There's a variety of techniques that you can use, such as using the boolean that you mentioned. You can also use a "sentinel", a dummy tab that you put at the end of tabList that has a maximum priority that is reserved for this purpose (i.e. no "real" tab can have this priority). This guarantees that the if condition inside the loop will be true when you reach the sentinel tab.

Finally, you can also implement your Tab to be Comparable, or define a separate Comparator for it, and make tabList an ordered collection. This way, you don't even need a sentinel, or even a foreach loop; you can just add the newTab to the sorted collection and have it figure out where to insert it. If tabList is a TreeSet, for example, the insertion will be O(log n). The other techniques mentioned so far is O(n).

polygenelubricants
+2  A: 

It is better practice to use a tab variable outside the scope of the for loop

Tab selected_tab = null;

for ( Tab tab: tabList ) {
    if (tab_I_want(tab)) {
       selected_tab = tab;
       break;
    }
}

// selected_tab is either null or the tab you want
Otto Allmendinger
A: 

tab is not available outside for loop. You can so many things. Using a boolean is one of them.

fastcodejava
A: 

Inside a foreach-style loop, I don't think you could know this. However, you could use an Iterator outside of the loop:

Iterator iter = tabList.iterator();
while (iter.hasNext()) {
  Tab newTab = iter.next();
  if( newTab.getPriority() < tab.getPriority() ) {
    newTab.insertBefore(tab);
    break;
  }
}

if (iter.hasNext()) {
  // You've still got elements left!
}
Kaleb Brasee
`iter` is not being advanced inside the loop. This code doesn't work.
polygenelubricants
Forgot to add the iter.next(). That's what you get when you don't write unit tests for your posts.
Kaleb Brasee
A: 

Instead of breaking you could raise an exception and catch it outside the loop. I forget the syntax in Java but Python would be something like this:

broken = False

try:
    for i in list:
        if i.condition == True:
            raise Exception
except Exception:
    # you know something has broken the flow
    broken = True

Although what if the last item broke? Technically speaking every item was inspected.

Oli
@Oli - that would be a bad idea. Creating, throwing and catching an exception is very expensive compared with setting a flag and doing a `break`.
Stephen C
The cost is generating the Exception instance, which while a lot larger than an if, or an iterator check, isn't huge and won't bankrupt the economy again unless you run through this code 100 times a second. It's not the best solution but it's an "out-the-box" idea for the OP if their actual flow fits it better.
Oli
+1  A: 

This wouldn't compile, because of the scope of the tab variable. You can do the following

Tab lastTab = null;
for (Tab tab : tabList) {
    if (..) {
       ..
       lastTab = tab;
    }
}
Bozho
why the downvote?
Bozho
A: 

Agreed with the above. I don't believe you can modify the tabList while it is being iterated either.

One alternate way of doing this is to find the position in the list you want to add into, and do the add operation then.

int i = 0;
for (; i < tabList.length; i++)
{
    if( newTab.getPriority() < tabList[i].getPriority() )
        break;
}

// this will shift the current item at that index value into the next one, and insert newtab into the specified index
tabList.add(i, newTab);
Sam
+1  A: 

The most obvious way to convert that into working code is:

insertBlock: {
    int newPriority = newTab.getPriority();
    for (Tab tab : tabs) {
        if (newPriority < tab.getPriority()) {
            newTab.insertBefore(tab);
            break insertBlock;
        }
    }
    newTab.insertBefore(endMarker);
}

Although it appears that not many people are familiar with the feature. As it happens, it was this feature that allows goto to be removed from the language.

Tom Hawtin - tackline