0

I have an arraylist of 50 RANDOM integers. I ask a user to remove a number and all occurences of that number are removed from the list. I did that using

while (randInts.contains(removeInt) )
{
  if (randInts.get(i) == removeInt)                 
   randInts.remove(randInts.get(i));
   i++;             

 } 

 System.out.println("\n" + randInts.toString());
 System.out.println("\n" + randInts.size());`

The other part of the problem is to prompt the user to enter another number. The removed number from above is inserted after each occurrence of the second prompted number. I am having issues with the second part as I keep getting IndexOutOfBoundsException.

2
  • 1
    can you post the code that is throwing the out of bounds exception...? Commented Sep 16, 2013 at 20:46
  • System.out.println("\n Please enter another integer in 1...10: "); int insertAfterInt = input2.nextInt(); while (randInts.contains(insertAfterInt) ){ if (randInts.get(i) == insertAfterInt) randInts.remove(randInts.get(i)); } System.out.println("\n" + randInts.toString()); System.out.println("\n" + randInts.size()); Commented Sep 17, 2013 at 17:38

8 Answers 8

1

Use a LinkedList instead; it's a much better choice when you need in-order traversal but not really random access, and when you need to insert and remove elements in the middle of the list.

You can accomplish what you're wanting (removing all instances of removeInt and inserting removeInt after every instance of insertAfterInt) with a simple traversal of the list's iterator:

ListIterator<Integer> li = randInts.listIterator();
while(li.hasNext()) {
    int i = li.next();
    if(removeInt == i)     // assumes removeInt is an int; use equals() for Integer
        li.remove();
    if(insertAfterInt == i)
        li.add(removeInt);  // the iterator will skip this element, so it won't get removed
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks it works. But I had to make some changes. May be it was a typo int i =li.next();
@dogbern Thanks, yes; I probably got confused by my tendency to use i instead of it for iterators. ;-) Feel free to edit answers for issues like that.
1

I see two big issues: You're not bounding i to anything, and you wrote an n^2 loop (you can do this in linear time).

You're shrinking the size of the `List` as you go...take this simple example:

Say you want to remove all instances of 5

Given a list that looks like {1,2,3,5,5}

When i = 3 you will remove the first 5, making the list look like: {1,2,3,5}

then you will attempt to remove the element at i = 4, but that element you want to remove is really now at i = 3, and you'll get the IndexOutOfBoundsException

You don't want to use a `contains`, as this expands the worst case performance of your loop to n^2, this would be faster:

int size = randInts.size() - 1;
for (int i = size; i >= 0; i--){
   if (randInts.get(i).equals(removeInt))
       randInts.remove(i);
}

6 Comments

And this is a textbook case of when to use a LinkedList instead of an ArrayList.
@chrylis I don't think you know enough about the list to make that call
@Chrylis I like your approach but the problem gives a hint that says the removeInt part can be accomplished with a very simple while statement.
@chrylis, also what approach would you take on the second part of the question for insertAfterInt?
@Cruncher He's doing lots of inserts and removes in the middle of the list. That's pretty much the distinguishing characteristic between use cases.
|
0
while (randInts.contains(removeInt) )
{

   if(i<randInts.size());
    {
  if (randInts.get(i) == removeInt)                 
   randInts.remove(randInts.get(i));
     }//if
   i++;             

 }while

Comments

0

I am guessing you are starting with a collection of 50 items (randInts) and removing the items that users enter (i)?

If that is the case, once your remove an item, your collection then only 49 indexes left and get gets by the index. Try something like...

if (randInts.contains(i)){
     randInts.remove(randInts.indexOf(i));
}

2 Comments

remove(i) - remove takes index not value as argument.
Actually remove takes either index or object according to the documentation. In this case without knowing what i is (Integer or int), value could just as easily worked. But to eliminate confusion I edited the answer.
0

This is n^2, but it should work

int i = 0;

    while(i < loFnumbers.size()){
        if(loFnumbers.get(i) == removeInt){
            loFnumbers.remove(i);
            continue;
        }
        i++;

    }

Comments

0

Here's an approach that avoids any state mutation (i.e. randInts is never modified):

package so;

import java.util.ArrayList;

public class SO_18836900 {

  public static void main(String[] args) {

    // build a collection of random ints
    ArrayList<Integer> randInts = new ArrayList();
    for (int i = 0; i < 50; i ++) {
      randInts.add((int)(Math.random() * 5));
    }

    // create a collection with all 3s filtered out
    ArrayList<Integer> filtered = filterOut(randInts, 3);
    System.out.println(filtered);
    System.out.println(filtered.size());

    // create a collection with a 99 inserted after each 4
    ArrayList<Integer> insertedAfter = insertAfter(randInts, 4, 99);
    System.out.println(insertedAfter);
    System.out.println(insertedAfter.size());

  }

  static ArrayList<Integer> filterOut(Iterable<Integer> xs, int toRemove) {
    ArrayList<Integer> filteredInts = new ArrayList();
    for (int x : xs) {
      if (x != toRemove) filteredInts.add(x);
    }
    return filteredInts;
  }

  static ArrayList<Integer> insertAfter(Iterable<Integer> xs, int trigger, int toInsert) {
    ArrayList<Integer> insertedAfter = new ArrayList();
    for (int x : xs) {
      insertedAfter.add(x);
      if (x == trigger) insertedAfter.add(toInsert);
    }
    return insertedAfter;
  }

}

Comments

0
if (randInts.get(i) == removeInt)                 
randInts.remove(randInts.get(i));
i++;  

You're never checking stopping conditions. Fix is:

while (randInts.contains(removeInt) )
{
    i=0;
   while(i<randInts.size()){

  if (randInts.get(i) == removeInt)                 
   randInts.remove(randInts.get(i));
   i++;             
}
 } 

6 Comments

while(i<randInts.size()); What does this accomplish exactly? Are you depending on another thread to increment i?
@Cruncher No, I'm making sure the OP doesn't exceed the bound. There's no need to even think about threading here.
My point here is that the loop has no body. If the condition was true the first time, it will be true forever.
@Cruncher Ah, I see what you were talking about. That was actually just a typo.
The dangers of using implicit blocks. I use them sometimes for super trivial if statements. There's a lot of code where I work with 4 levels deep of implicit blocks. It's a nightmare. If you add a line of code anywhere it just breaks.
|
-1

Dont use == on "Integers" you are comparing references.
Either unbox into int or use equals(

2 Comments

That's true, but it's not the only issue here.
well, I assumed that he "zeroes" his i just before while - he did not mention i initialization in his snippet. And if he did just that then it caused indexoutofbounds.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.