I want to rearrange an ArrayList by iterating through it and copying each element to a specific place in a new list.
In this case I want to move an element to the end of the list. For example, if the list is ABCDE and j == B then the new list should be ACDEB.
Here's my code:
private ArrayList<Job> schedule;
private ArrayList<Job> tempSchedule;
...
schedule = input;
tempSchedule = new ArrayList<Job>(schedule.size());
...
private void moveJob(int j) {
for(int i = 0; i < schedule.size(); i++) {
if(i == j) { //move to the end
tempSchedule.set(schedule.size()-1, schedule.get(i));
} else {
if(i > j && i <= schedule.size() -1) { //move one position back
tempSchedule.set(i - 1, schedule.get(i));
} else { //same position
tempSchedule.set(i, schedule.get(i));
}
}
}
schedule = tempSchedule;
u++;
}
Right now I get an IndexOutOfBoundsException: Index: 0, Size: 0 at tempSchedule.set
I guess the problem is with this line
tempSchedule = new ArrayList<Job>(schedule.size());
Also please explain how to make deep copies.
Edit: Thanks for all the answers. I got it to run by simply removing the item and adding it at the end, like suggested.
The reason I wanted to construct a new list is because I might have to do more complex rearrangements at some point.
First, go read the javadoc on ArrayList and collections.
new ArrayList(capacity) doesn't copy, it just allocates a list with that capacity. To copy the list (and it's not a clone, it's a by reference copy, again you need to go back to basics) would be new ArrayList(oldArrayList).
Secondly, Your test has size 0, so there's no objects in it, so get(0) (correctly and as per spec) throws an index out of bounds exception because your list is empty.
Beyond that, neither set nor get will modify the list, so if you had created your copy correctly and it's contents were ABCD and you executed that operation, it's contents would then be ABCB. what you want is.
X = tempSchedule.remove(i) // removes element at I
tempSchedule.add(X) // adds element to end of list
tempSchedule is initialized to be empty:
tempSchedule = new ArrayList<Job>(schedule.size());
You can't use set on an empty ArrayList. It expects the index you are replacing to already have a value.
You get the exception in this line - tempSchedule.set(i, schedule.get(i)); - when i==0.
set calls RangeCheck :
/**
* Checks if the given index is in range. If not, throws an appropriate
* runtime exception. This method does *not* check if the index is
* negative: It is always used immediately prior to an array access,
* which throws an ArrayIndexOutOfBoundsException if index is negative.
*/
private void RangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);
}
As you can see, the index you pass to it must be smaller than the current size of the list.
The problem is that your tempSchedule list is empty. set() overwrites the element at the given position. If your list is empty, it can't do that.
This might be a little confusing since you wrote new ArrayList<Job>(schedule.size()). But the parameter you are passing doesn't set the size but the initial capacity, meaning the initial size of the underlying array, which can be used before it has to be resized.
Reason is when you define arrayList with size of schedule, its an empty list i.e. contains nothing.
So when you try to set an element (which is used to replace the existing element), it compares the index with size of your list and finds that index is 0 and size is 0 as well.
Note just by passing size as constructor, you are not changing the size of arrayList. So in order to avoid this, you need to use:
tempSchedule = new ArrayList<Integer>(schedule);
instead of
tempSchedule = new ArrayList<Integer>(schedule.size());
You have the IndexOutOfBoundsException because you are using schedule.size in your for loop while it's null you have to use tempSchedule.size instead.
And you are comparing i and j while you have to compare tempSchedule.get(i) and j.
You have a syntax fallacy as every other answer stated.
I'm more concerned on your approach.
Can't you just simply do:
private void moveJob(int j) {
Job toMove = tempSchedule.get(j);
tempSchedule.remove(j);
tempSchedule.add(toMove);
}
Or yet more concise:
private void moveJob(int j) {
tempSchedule.add(tempSchedule.remove(j));
}
Related
So my friend created a queue class which has an instance variable size = 0; and for the add method he uses.
But what will happen to index 0 in this case?
It will not have an elements declared to it since add starts from size++. Which is 1 starting position.
public void add(T data) {
if(size > elements.length) {
throw new QueueException("Queue is full");
}
elements[size++] = data;
}
size++ returns the size value before it gets incremented in the background. Because of that the elements[0] will be assigned. See Oracle Tutorial on incrementing.
The problem is with the last element. The code will attempt to assign elements[elements.length] which is above the array capacity. The guard should be:
if (size >= elements.length) {
throw new QueueException("Queue is full");
}
Really need help with this as a Patient is not getting set to replace the null. We have to create an arraylist of 50 nulls so the iterator goes through the list and if it finds a null it will set it to the patient. The problem is no patients are getting set to the null. We have to return the bed number at the end too.
protected int amountOfBeds = 50;
ArrayList<Patient> bedList = new ArrayList<Patient>(amountOfBeds);
public int admitPatient(Patient illPatient) {
int index = -1;
if(illPatient.getAge() > 0 && amountOfBeds > size()) {
//if it is null then set to patient
//if it not null then we assume its a patient so we skip
Iterator<Patient> itr = bedList.iterator();
try{
while(itr.hasNext()) {
int bedIndex = bedList.indexOf(itr.next());
if(bedList.get(bedIndex).equals(null)) {
bedList.set(bedIndex, illPatient);
index = bedIndex +1;
break;
}
}
}catch(NullPointerException e) {
e.getMessage();
}
}
return index;
}
Simple way to create 50 nulls list is this
List<Patient> list = Collections.nCopies(50, null);
quick way to find index of null is this
int i = list.indexOf(null);
In Java, an ArrayList is basically an array, that can change its size during execution time. Since you seem to have a fixed amound of beds, an array would probably be better here.
The constructor new ArrayList(50) doesn't create an ArrayList with 50 elements. It creates an empty ArrayList, but gives Java the "hint, that there will probably be inserted 50 elements into the ArrayList. If you don't give such a hint, the ArrayList starts with little space and is periodically made bigger, if it gets too small too accomodate all items you want to insert. This takes time, so if you already know how many items you will insert (even if you only know it approximately) this constructor makes your code faster.
However, you have to think if you really need to do this the way you just wanted to do. Whouldn't it be easier, to just have an empty ArrayList, to which you can add or delete elements just as you want to (without a complicated logic, which replaces null with an element. You could then just add if (array.size() >= 50) // it is full, so some special case may be needed here to make sure there are never more elements in the array than you want.
I'm getting an ArrayIndexOutOfBoundsException while removing postions because positions start from 1 but the array index starts from 0. Could you provide an explanation on how to solve this?
if (isChecked && groupName.equals(OLIConstants.FAILED_TO_ACTIVATE))
{
count = count + 1;
arrActivation.add(childPosition);
context.getSummaryFragment().getOli(arrActivation,groupPosition);
if (!context.getSummaryFragment().activateSystem.isEnabled())
{
context.getSummaryFragment().enableButton(true);
}
}
else if (!isChecked && groupName.equals(OLIConstants.FAILED_TO_ACTIVATE))
{
count = count - 1;
arrActivation.remove(childPosition);
}
context.getSummaryFragment().getOli(arrActivation,groupPosition);
if (context.getSummaryFragment().activateSystem.isEnabled() && count <= 0)
{
context.getSummaryFragment().enableButton(false);
}
}
I'm gonna make an assumption based on your code:
childPosition is the data you wanna store in ArrayList arrActivation.
arrActivation.add(childPosition);
childPosition is an integer (because you're getting an array index out of bound exception.
arrActivation.remove(childPosition);
Now, if you try to add an integer and remove it using the same parameter, you might get the AIOOB exception. Take a look:
ArrayList here = new ArrayList();
here.add(5);
// The following line will exception because
// The length of the array list is 1 at this point
here.remove(5);
But this will work:
ArrayList here = new ArrayList();
here.add(5);
// The following line will not exception
here.remove(Integer.valueOf(5));
Because now we're using the remove(Object o) (which finds the data with Object o, and remove the first occurance) function instead of the remove(int index) (which tries to remove the arraylist's index's index) function.
I hope this helps :)
You can access array by using arrActivation.add(childPosition-1);
Hope this will solve your issue.
When you create an arraylist of type Integer in Java what are the default values? I need to check if an arraylist is full and I was going to get the size of the array then get the value at the last index and check if it was the default value.
Is there a better way? What would be the default value?
Hope that makes sense. Cheers
int size = a.size();
int last = a.get(size);
if( last == null )
{
return true;
}else{
return false;
}
Edit;
Is it possible to create an ArrayList with a max size that you can not go over to stop it dynamically expanding?
When you create an ArrayList and you use size() would that return the actual size or the amount of elements in the arraylist?
When doing this to create a max size would the default values be null?
public boolean isFull()
{
int size = a.size();
int last = 0;
try{
last = a.get(size-1);
}catch (Exception e){
}
if( last == null )
{
return true;
}else{
return false;
}
}
I currently have this, how does it look? Does this make sense now?
When you declare an ArrayList it is empty. It is also a dynamic container meaning it will grow so for you to ask if it is "full" is more of a constraint you'd need to add to your code.
So, if you want to achieve a goal like you describe.
List<Integer> list = new ArrayList<Integer>();
int MAX_ELEMENTS = 5; //Set this to however you want to constrain the datatype
public boolean addElement(Integer value) {
if (list.size() < MAX_ELEMENTS) {
list.add(value);
return true;
} else {
return false;
}
}
public boolean isFull() {
return (list.size() == MAX_ELEMENTS);
}
public Integer getLast() {
if (!list.isEmpty())
return list.get(list.size()-1);
else
return null;
}
As others have stated though, if you generate a list with a preset size as such:
List<Integer> list = new ArrayList<Integer>(10);
You'd have a list of 10 elements large all being null in value. Should you add additional elements the list will still grow larger than 10 elements unless you constrain it like I did above.
If you haven't actually added Integers to the ArrayList, then any get() on the list will return an IndexOutOfBoundsException.
The size() method returns the number of elements in the list (i.e. how many you have added to it), not the current capacity.
By default ArrayList capacity is 10. All of them are null by default until you add your elements into it. But calling size() will give you number of elements that you have added. It wont give 10 as result(default null values will not be considered). Twist here is if you add null values to the list then they are included while calculating size(). Example if you add 3 valid Integers and 2 null values into the list then size() will return 5. Eclipse debugging will help you in finding this dynamic increasing of its capacity.
When you create an ArrayList, inside the ArrayList class, there is an array of elements. Those elements are set to null because they do not refer to any instance of an Integer object. Bare in mind, that isn't the same as an int.
Moreover, an ArrayList doesn't get full. It is dynamic, and will increase in size when it needs to.
Edit: in response to your edit about setting a maximum size, if you want a maximum size then I'm not sure why you'd want an arraylist. But if you want to stick with an ArrayList class, I would create my own class that is a subclass of arraylist, and override the add method with a check to ensure the value of size() isn't over a fixed amount.
There is not such thing like "full" ArrayList. The size() method will return the number of elements it currently holds.
Do you want to simply constraint the list to a given size, or do you want to check if it is larger than a given size?
Check if list is larger than:
if (list.size() > limit)
System.out.println("List too large");
Its not possible to constraint the size of an ArrayList - you can however create your own subclass of ArrayList that does just that:
public class LimitedList<E> extends ArrayList<E> {
private int limit;
public LimitedList(int limit) {
this.limit = limit;
}
public boolean add(E e) {
// only add if the limit is not exceeded
if (size() < limit)
super.add(e);
}
// overwriting the addAll()-methods is left as an excercise to the reader
}
You only need to decide what the list should DO when one attempts to add more elements than the limit allows. Either just ignore the elements or throw an Exception.
ArrayLists have no default values. If you give the ArrayList a initialCapacity at initialization, you're just giving a hint for the size of the underlying array—but you can't actually access the values in the ArrayList until you add the items yourself.
Any List implementation has a isEmpty() method you can use.
The method public boolean remove(Object o) of List removes an object from list but does not shift the elements following.Just nulls the object value.
IMHO this is an uninintuitive design choice since the size of the list before and after removal remains the same.
Is there an elegant way to get a list with the elements shifted?
Thanks
No, that's not what it does. The element is removed and all indices following it are reduced by one. What makes you think it acts differently?
According to the Java API here it sais that the remove function of List DOES shift
Removes the element at the specified position in this list (optional operation). Shifts any subsequent elements to the left (subtracts one from their indices). Returns the element that was removed from the list.
EDIT:
Main class:
import java.util.ArrayList;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
ArrayList<A> x = new ArrayList<A>();
A one = new A("one");
A two = new A("two");
A three = new A("three");
A four = new A("four");
A five = new A("five");
A six = new A("six");
A seven = new A("seven");
A eight = new A("eight");
A nine = new A("nine");
A ten = new A("ten");
x.add(one);
x.add(two);
x.add(three);
x.add(four);
x.add(five);
x.add(six);
x.add(seven);
x.add(eight);
x.add(nine);
x.add(ten);
for(A item:x){
System.out.println(item.getStr());
}
x.remove(four);
Iterator<A> i = x.iterator();
while(i.hasNext()){
A item = i.next();
System.out.println(item.getStr());
}
}
}
The A Class:
public class A {
private String str;
public A(String x){
this.str = x;
}
public String getStr(){
return this.str;
}
}
works perfectly! no null pointer exception.
This is how it should be done. the first For loop is the alternative syntax for what i did wit the Iterator object. Actually Java automatically translates the first for loop in something that looks like the while loop.
If you look at ArrayList remove implementation, it uses a local method fastRemove(index) as follows:-
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
}
It does use arraycopy which is a proof that you get whole new list of fresh objects and not the null filled in between. Is this a proof?
The contract for java.util.List implies that calling remove will cause the size() to be decremented. If you're talking specifically about java.util.ArrayList then you might be right about the internal array not shifting its elements, but this is an implementation detail that shouldn't matter to you in 99% of all cases. If it still does matter, then you're trying to optimize for a specific situation and you should probably implement your own List or use something like java.util.LinkedList.
Either your observation is wrong or you are using some other kind of List implementation (and not ArrayList) that doesn't shift the elements to the right of the element being removed. Can you post your code?
If you look at the java.util.ArrayList source code in JDK8, you will see that the remove(Object o) method effectively copies the elements to the right of the element being removed, to the same array starting from the index of the element being removed. Look at the ArrayList source code for more info:
If all you need is an array of the data, then just call toArray().