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
}
}
}
Related
Spotify's lyrics API provides an Array of miliseconds to mark when the lyric line has changed. Having a Media Player that updates it's position every 50ms, how should i code in Kotlin the way to find the correct lyric line? The position param can be in the middle of two values of the array, so I want to get the lowest one of that two.
I tried to get the lowest value compared to the position parameter but lol, it will always be the first value of the Array... Silly fault of mine.
The problem is that I have a third one that indicates the range of that two value. For example: I have an Array of [45, 78, 125, 198]. If I pass the position param where it's value is 95, I want to return the 78 (that is the lowest value from itself, the position param and 125).
/** Input data for example (from your comment). */
val yourArray = arrayOf(45, 78, 125, 198)
val inputValue = 95
/** How to get needed index. */
val resultIndex = yourArray.indexOfLast { it < inputValue }.takeIf { it != -1 }
If you get resultIndex == null - it means you don't have value inside your array which lower then your inputValue.
I think it's simpler than find indexOfFirst and compare result later. And absolutely better and safer when sort() solution.
Insert the position param into the array, sort it, find its index and use it to get the closest value.
val array: MutableList<Long> = mutableListOf(4L, 9L, 5L, 1L)
val position = 7L
array.add(position)
println(array[array.sorted().indexOf(position) - 1])
Output: 5
If I correctly understand, you need simply use min function for compare two numbers in Kotlin and find the low one: link
Here’s a way to do it without having to make two copies of the list and doing a sort.
val foundIndex = lyricTimesList.indexOfFirst { it > inputTime }
val result = if (foundIndex == -1) lyricTimesList.size - 1 else foundIndex - 1
Note the result could be -1 if the input time is less than the first number in the list.
I'm trying to implement removing chosen TextViews from my ListView.
The one way to do this according to android dev reference is by using SparseBooleanArray. The problem is, I don't understand the logic behing this array and every time I call the getCheckedItemPositions(), method returns the empty array.
Here is the sample of my code:
List<Record> records = new RecordDAO(this).findAll(); //gets all records saved in ListView from database
SparseBooleanArray checkedPositions = recordListView.getCheckedItemPositions();
for(int i = 0; i < records.size(); i++){
if(checkedPositions.valueAt(i)){
System.out.println("chosen at pos: " + i);
}
}
I choose the last 2 TextViews press button
and the output is:
I/System.out: chosen at pos: 0
I/System.out: chosen at pos: 1
How do I properly solve my problem?
Can anyone explain me how does
the SparseBooleanArray working?
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.
I am trying to display a list from current year plus five year in a Spinner item. But getting error java.lang.IndexOutOfBoundsException: Invalid index 2014, size is 0
I used this code,
ArrayList<String> years=new ArrayList<String>();
Calendar cal=Calendar.getInstance();
int curYear= cal.get(Calendar.YEAR);
for(int i=0;i<6;i++)
{
years.add(curYear+i, null);
}
Spinner spnYear= (Spinner) findViewById(R.id.spnYear);
ArrayAdapter<String> adapter=new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, years);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spnYear.setAdapter(adapter);
Please help.
Thanks.
When you use add() with two parameters, the first is the index you would like to add it at. You'll want to just call years.add(String.valueOf(currYear + 1)). I've also added the String.valueOf() around the item you're adding, because you have an ArrayList<String>
It's how you're adding things to your ArrayList. For one, you're trying to add an int curYear + i to an ArrayList<String>. That won't work. Second you're adding them in such a way that you're not actually passing an object to the list. The version of add you're using add(int index, E object) takes the index as its first argument - not what you want to add to the list. Your second argument, which is what you actually want to add, is null. That explains why you're getting list size of 0. You should just add your values normally and know that index 0, 1, 2, 3, 4 will be the next 5 years.
here is your issue
for(int i=0;i<6;i++) {
years.add(curYear+i, null);
}
you are using the add method that takes a first paramter the index and as second the object. The documentation states that it throws
IndexOutOfBoundsException - if the index is out of range (index < 0 || index > size()).
At the first iteration size() returns 0, and you are try to put the element at position 2014
Change it in
for(int i=0;i<6;i++) {
years.add(String.valueOf(curYear+i));
}
I've a ListView allowing multiple selection configured with an ArrayAdapter, everything works fine but when I try to set to false some selected items the getCheckedItemCount value doesn't change
Just to replicate the behavior I unselect all items using the code shown below and the printed value is the same before and after the getCheckedItemCount call
Why?
for (MyObject post : list) {
int position = photoAdapter.getPosition(post);
System.out.println("count before " + photoListView.getCheckedItemCount());
photoListView.setItemChecked(position, false);
System.out.println("count after " + photoListView.getCheckedItemCount());
}
Obviously to unselect all items we must call clearChoices() but the code above is used only to demonstrate the problem
#dafi i am not sure this is working in your case but below solution give me right count. The easiest solution is to clear the checked count manually.You just try it.
this.markersList.clearChoices();
for(int i = 0; i < this.markersList.getCount(); i++)
{
this.markersList.setItemChecked(i, true);
}
Try out this solution.