ArrayList.add() causing OutOfMemory error? - android

For the first time today, I've met an OutOfMemory Error. I'm trying to calculate moving averages out of some data into an ArrayList, and had a crash at the first .add() step. The method is shown below
public ArrayList<Long> getNdaySMA(List<HistoricalQuote> history, int range){
long sum =0;
long SMA = 0;
ArrayList<Long> SMAs = new ArrayList<Long>();
//realRange is made due to the differences in defining "range in calculation vs speech
//a 10 day range for day 9 is actually from prices of day0 to day9, inclusive
int realRange =range-1;
//First step, add in placeholder 0s for the days within the range that have no value
//so if 10 day range, we have 0-> 9
for (int i=0;i<i+realRange;i++){
SMAs.add(i,0L);
}
//Next, actually calculate the SMAs for i.e. day 10
for (int i =0;i<history.size();i++){
//should be k<10, 0......9 = 10 days
for(int k=i+realRange;k==i;k--){
//Sum first from k=i+range-1 , go down to i.
//This should give us a value of RANGE
sum +=history.get(k).getClose().longValue();
}
//after summing up, we add calculate SMA and add it to list of SMAs
SMA = sum/range;
//we add the corresponding SMA to index i+range, made up of values calculated from before it
//to excel
SMAs.add(i+realRange,SMA);
sum =0;
}
return SMAs;
}
The stacktrace is as follows
java.lang.OutOfMemoryError
at java.util.ArrayList.add(ArrayList.java:154)
at com.xu.investo.MethodDatabase.getNdaySMA(MethodDatabase.java:46)
Where Line 46 refers to
SMAs.add(i,0L);
Is this error occuring due to the use of the Long number format? Any suggestions are welcome.

looks like infinite loop:
for (int i=0;i<i+realRange;i++)
i will always be less then i+realRange for realRange greater then zero:

I think I've identified the problem.
I may have created an infinite loop at this line
for (int i=0;i<i+realRange;i++){
SMAs.add(i,0L);
}

Related

Fragment crash: IndexOutOfBoundsException: Invalid index x, size is x after updating my database [duplicate]

When I do
ArrayList<Integer> arr = new ArrayList<Integer>(10);
arr.set(0, 1);
Java gives me
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.set(Unknown Source)
at HelloWorld.main(HelloWorld.java:13)
Is there an easy way I can pre-reserve the size of ArrayList and then use the indices immediately, just like arrays?
How about this:
ArrayList<Integer> arr = new ArrayList<Integer>(Collections.nCopies(10, 0));
This will initialize arr with 10 zero's. Then you can feel free to use the indexes immediately.
Here's the source from ArrayList:
The constructor:
public ArrayList(int initialCapacity)
{
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
this.elementData = new Object[initialCapacity];
}
You called set(int, E):
public E set(int index, E element)
{
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
Set calls rangeCheck(int):
private void rangeCheck(int index)
{
if (index >= size) {
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
}
It may be subtle, but when you called the constructor, despite initializing an Object[], you did not initialize size. Hence, from rangeCheck, you get the IndexOutOfBoundsException, since size is 0. Instead of using set(int, E), you can use add(E e) (adds e of type E to the end of the list, in your case: add(1)) and this won't occur. Or, if it suits you, you could initialize all elements to 0 as suggested in another answer.
I believe the issue here is that although you have suggested the allocated space of entries in the Array, you have not actually created entries.
What does arr.size() return?
I think you need to use the add(T) method instead.
Programming aside, what you are trying to do here is illogical.
Imagine an empty egg carton with space for ten eggs. That is more or less what you have created. Then you tell a super-precise-and-annoying-which-does-exactly-what-you-tell-him robot to replace the 0th egg with another egg. The robot reports an error. Why? He can't replace the 0th egg, because there is no egg there! There is a space reserved for 10 eggs, but there are really no eggs inside!
You could use arr.add(1), which will add 1 in the first empty cell, i.e. the 0-indexed one.
Or you could create your own list:
public static class PresetArrayList<E> extends ArrayList<E> {
private static final long serialVersionUID = 1L;
public PresetArrayList(int initialCapacity) {
super(initialCapacity);
addAll(Collections.nCopies(initialCapacity, (E) null));
}
}
Then:
List<Integer> list = new PresetArrayList<Integer>(5);
list.set(3, 1);
System.out.println(list);
Prints:
[null, null, null, 1, null]
This is not an Java-specific answer but an data structure answer.
You are confusing the Capacity concept with the Count (or Size) one.
Capacity is when you tell the list to reserve/preallocate a number of slots in advance (in this ArrayList case, you are saying to it create an array of 10 positions) in its' internal storage. When this happens, the list still does not have any items.
Size (or Count) is the quantity of items the list really have. In your code, you really doesn't added any item - so the IndexOutOfBoundException is deserved.
While you can't do what you want with arraylist, there is another option: Arrays.asList()
Capacity is used to prepare ArrayLists for expansion. Take the loop
List<Integer> list = new ArrayList<>();
for(final int i = 0; i < 1024; ++i) {
list.add(i);
}
list starts off with a capacity of 10. Therefore it holds a new Integer[10] inside. As the loop adds to the list, the integers are added to that array. When the array is filled and another number is added, a new array is allocated twice the size of the old one, and the old values are copied to the new ones. Adding an item is O(1) at best, and O(N) at worst. But adding N items will take about 2*1024 individual assignments: amortized linear time.
Capacity isn't size. If you haven't added to the array list yet, the size will be zero, and attempting to write into the 3rd element will fail.

java.lang.IndexOutOfBoundsException: Invalid index 2, size is 2

Scenario:-
I have two ArrayList
list contains images
postList contains position of selected images
now when ever i am selecting the images and press delete menu ,it should delete the selected images .
when i am running the code in debug ,its working fine and give the desire output.
but when i am running it normal mode ,its crashing and giving above exception.
if (posList.size() > 0)
{
Toast.makeText(getBaseContext(), "i value" +posList.size(),
Toast.LENGTH_SHORT).show();
for (int i = 0; i < posList.size(); i++)
appAdp.list.remove(appAdp.list.get(posList.get(i)));
appAdp.notifyDataSetChanged();
posList.clear();
Toast.makeText(getBaseContext(), "You deleted selected items",
Toast.LENGTH_SHORT).show();
}
return true;
postList values here
#Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
boolean checked) {
posList.add(position);
error showing here
appAdp.list.remove(appAdp.list.get(posList.get(i)));
logcat:-
java.lang.IndexOutOfBoundsException: Invalid index 2, size is 2
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)
at java.util.ArrayList.get(ArrayList.java:304)
why its behaving like this ,not getting any clue.
Thanks for any help.
You are trying to perform operation on Same ArrayList because of that when ever you are remove elemnt from the ArrayList then its size will reduce so, You'll get ArrayIndexoutofBoundsException.
i.e when you remove item from the appAdp.list , then the size of the appAdp.list will also change
consider if your list has originally 3 elemnts.
you have the position in your posList 0,2
then when you remove item from the 0 item from appAdp.list, its size will become 2 for the next time when you try to remove item at position 2, you will get AIOBE
Solution:
Save all items that needs to be removed in separate List and the use removeAll(list) method to remove items from your appAdp.list
Example:
ArrayList<yourappListtype> templist=new ArrayList<yourappListtype>();
for (int i = 0; i < posList.size(); i++)
templist.add(appAdp.list.get(posList.get(i)));
And then
appAdp.list.removeAll(templist);
try this code,
postList.remove(position);
then,
notifyItemRangeChanged(positon,postList.size());
Before you change the data source of adapter, you can call adapter's notifyDataSetInvalidated() function to make the origin data source invalid, then call adapter's notifyDataSetChanged() after finish changing the data source.
remember that index are starting from zero. I think you when get position it is +1 higher than index of array, so you get out of bounds exception
The error is Invalid index 2, size is 2
Possible issue is your posList.size()=2 where as appAdp.list.size()<2
Make sure that your appAdp.list has more than two entries.
if (posList.size() >0)
i=appAdp.list.size();
while(i<=posList.size() && i<=appAdp.list.size())
{
appAdp.list.remove(appAdp.list.get(posList.get(i)));
i--;
}
The basic meaning of the exception java.lang.IndexOutOfBoundsException: Invalid index x, size is y where x and y are the index position and size respectively means you are attempting to get value at a position that does not exist. Take for example an ArrayList with a size 2, typically you would want to get value(s) by specifying position index which in this case the valid position would either be 0 or 1 and end up specifying a position 2 (index 2 does not exist). I believe understanding basic meaning of Java errors will save you a lot of valuable time in your development.
just use break command at the end of for loop, like this:
fun deleteUser(userID: Int) {
for(i in 0 until usersList.size) {
if (usersList[i].id == userID) {
usersList.removeAt(i)
notifyItemRemoved(i)
break
}
}
}

Using limit () and offset () in QueryBuilder (ANDROID , ORMLITE)

#SuppressWarnings("deprecation")
public List<Picture> returnLimitedList(int offset, int end) {
List<Picture> pictureList = new ArrayList<Picture>();
int startRow = offset;
int maxRows = end;
try {
QueryBuilder<Picture, Integer> queryBuilder = dao.queryBuilder();
queryBuilder.offset(startRow).limit(maxRows);
pictureList = dao.query(queryBuilder.prepare());
} catch (SQLException e) {
e.printStackTrace();
}
return pictureList;
}
I have a table of Pictures in the database, and must return a limited list, 20 lines at a time.
But when I use ex: QueryBuilder.offset(11).limit(30);
I can not return the list limited to 20 lines.
The list only comes to me with the limit.
It's as if the offset remain always with value 0
ex: (0 - 30)
Is there any other way to return a limited list for initial index and end index?
Could anyone help me?
This question was asked two months ago, but I'll answer if anyone stumbled on the same problem as I did.
There's misunderstanding about what offset means in this case, here follows what SQLite Documentations says about it
If an expression has an OFFSET clause, then the first M rows are omitted from the result set returned by the SELECT statement and the next N rows are returned, where M and N are the values that the OFFSET and LIMIT clauses evaluate to, respectively.
Source
Based on your query, you'll return 30 lines starting at the #11 line.
So the correct way is:
queryBuilder.offset(startRow).limit(20);
With limit being the number of rows that will return, not the ending row.
pictureList = dao.query(queryBuilder.prepare());
And the returned List with the first value starting on pictureList.get(0)
Edit: #Gray 's help on comments

Trying to only do math functions on edittexts users have entered information in on android

I have a 10-field average lap calculator. However, in testing, someone said they normally only run X laps in practice, vs. 10 (let's say 7).
I think I could use an if statement, but there'd be at least 10 of them and a bunch of clumsy code, and I'm not sure on arrays/switch statements exactly. I think all of those might be possible, but my low level of experience has yet to fully comprehend these useful tools.
CURRENT CODE:
double tenLapAvgVar = ((lap1Var + lap2Var + lap3Var + lap4Var + lap5Var + lap6Var + lap7Var + lap8Var + lap9Var + lap10Var) / 10);
So essentially, if someone leaves a field or fields blank, I want to calculate the average based on the populated fields, not 10 (if they leave 3 fields blank, calculate based on 7, for instance). Any help you guys could provide would be much appreciated, thanks!
You could have an ArrayList<EditText> object and a method which iterates over it and adds up the values. Something like:
public double getLapAverage()
{
int noOfCompletedLaps = 0;
double lapAve = 0;
double lapsTotal = 0;
for(EditText text : textBoxes)
{
if(text.getText().toString().length() > 0)
{
//psuedo code, and assuming text is numerical
lapsTotal += Double.parse(text.getText().toString());
noOfCompletedLaps++;
}
}
if( noOfCompletedLaps > 0)
{
lapAve = lapsTotal / noOfCompletedLaps;
}
return lapAve;
}
Maybe it would be better if you used an array instead of 10 different variables.
Then you can use a for statement and initialize them to 0, afterwords let the user fill the array and count how many are not zero.
Finally sum up all the array and divide by the count you previously calculated.

Shuffle Class Instances

My program is a quiz which asks questions for US States
I create three instances of a class say State
State st1 = new State();
State st2 = new State();
State st3 = new State();
like it asks a question about a state what is capital of st1.name
and line below that it gives 3 option
String Builder sb;
sb.append("What is Capital of "+st1.name+"\n");
sb.append("\n"+st1.capital);
sb.append("\n"+st2.capital);
sb.append("\n"+st3.capital);
mainText.setText(sb.toString);
now the problem is every time it comes up with correct answer in first line...
how do i avoid that ?
Put the correct answer in a random spot using Java's Random class
Random.nextInt(3) will give you a random number between 0 and 2. Put your correct answer into an array of size 3 at location and put the two wrong answers in the remaining locations. Then loop through that array and sb.append(array[i]); (i between 0 and 2) to get your random ordering of state capitals.
Create an ArrayList the pull the objects out randomly.
This code is totally untested, but I don't think it's too far off...
This will (theoretically) list the answers in totally random order.
ArrayList<State> states = new ArrayList<State>();
Random rand;
states.add(new State());
states.add(new State());
states.add(new State());
sb.append("What is Capital of "+states.get(0).name+"\n");
int randomNum = 0;
while (states.size() > 0) {
randomNum = rand.nextInt(1 - states.size() + 1);
sb.append("\n"+states.get(randomNum).capital);
states.remove(randomNum)
}
mainText.setText(sb.toString);

Categories

Resources