ArrayIndexOutOfBoundsException when doing removeAt in map - java

I try to remove a value from a map when unchecked but for some reason, it gives me an IndexOutOfBoundsException
itemView.checkBox.setOnCheckedChangeListener { buttonView, isChecked ->
item.isChecked = isChecked
if(isChecked){
map.put(position,true)
} else {
map.removeAt(position)
}
}
Here I have 2 checkboxes, when I check both is ok. When I uncheck the first one is ok, but when I try to uncheck also the second one it crashes with this error
java.lang.ArrayIndexOutOfBoundsException: src.length=11 srcPos=2 dst.length=11 dstPos=1 length=-1
The problem is at map.removeAt(position) but I don't know why it is failing because that position is an element from the array that actually exists.
I'm using a SparseBooleanArray.

The problem is not the position of the array as I said, because this array never changes (I never delete any items on it, just removing values on the map that contains this mapped booleans values)
So the problem was in removeAt(position)
Example
I have a Map array with 2 values
0 - true
1 - true
If I do map.RemoveAt(0) now I have
1 - true (actually in position 0 right now)
but now if I try to do again map.removeAt(1) there is not element in position 1 so that is why is outbounded
I have solved it by removing by key in the map
map.remove(position,true)
So this will remove that 1 - true value and just the values with true as the value of that map

Your code doesn't show where position is being set, but if I had to guess, you probably need to be doing position - 1
Remember that your arrays are 0 indexed!

I saw the answer that you posted. Yes, you have figured that out correctly. You were getting the IndexOutOfBoundException because the position that you are looking for was already removed.
However, you do not have to use the key-value pair to remove that element from your map. It reduces the scalability of your Map object as somewhere down the road, the value might be changed and if you are not aware of that change, you might run into a similar problem, where the data will not be removed. Let us take the following example.
0 - true
1 - true
Now somewhere you have changed the value for key 1 to false. Hence when you will call the map.remove(position, true) this will not find anything to remove.
I would recommend using the remove function with the key only. The following should suffice.
if (map.containsKey(position)) map.remove(position);
I hope that helps!

Related

Java stream - delete everything after first match

I have a linked hash list of some DTO that contains name (String) and isActive (boolean) properties. I need to iterate over all of them from first to last and check, if any of members have false value in isActive. When I find this element, I need to cut off this element and the rest of list and return just elements before this one.
I would like to use java streams to solve this problem.
I've tried to use stream and filter elements via predicate to check if element is active but that does not match the logic I want. As I said, I need to find first element that is inActive and cut it and everything after from the list.
If we have this list of ElementDto in LinkedHashSet<>
0 - name:test, isActive:true
1 - name:test2, isActive:true
2 - name:inActive, isActive:false
3 - name:activeAfterInactive, isActive:true
The expected output would be list with elements 0,1
The following should work for any ordered collection:
elementCollection.stream().takeWhile(el -> el.isActive())...

Hash items in a 2d array, but only on one index

So, I have a 2d array (really, a List of Lists) that I need to squish down and remove any duplicates, but only for a specific field.
The basic layout is a list of Matches, with each Match having an ID number and a date. I need to remove all duplicates such that each ID only appears once. If an ID appears multiple times in the List of Matches, then I want to take the Match with the most recent date.
My current solution has me taking the List of Matches, adding it to a HashSet, and then converting that back to an ArrayList. However all that does is remove any exact Match duplicates, which still leaves me with the same ID appearing multiple times if they have different dates.
Set<Match> deDupedMatches = new HashSet<Match>();
deDupedMatches.addAll(originalListOfMatches);
List<Match> finalList = new ArrayList<Match>(deDupedMatches)
If my original data coming in is
{(1, 1-1-1999),(1, 2-2-1999),(1, 1-1-1999),(2, 3-3-2000)}
then what I get back is
{(1, 1-1-1999),(1, 2-2-1999),(2, 3-3-2000)}
But what I am really looking for is a solution that would give me
{(1, 2-2-1999),(2, 3-3-2000)}
I had some vague idea of hashing the original list in the same basic way, but only using the IDs. Basically I would end up with "buckets" based on the ID that I could iterate over, and any bucket that had more than one Match in it I could choose the correct one for. The thing that is hanging me up is the actual hashing. I am just not sure how or if I can get the Matches broken up in the way that I am thinking of.
If I understand your question correctly you want to take distinct IDs from a list with the latest date by which it occurs.
Because your Match is a class it is not as easy to compare with each other because of the fields not being looked at by Set.
What I would do to get around this problem is use a HashMap which allows distinct keys and values to be linked.
Keys cannot be repeated, values can.
I would do something like this while looping through:
if(map.putIfAbsent(match.getID(), match) != null &&
map.get(match.getID()).getDate() < match.getDate()){
map.replace(match.getID(),match);
}
So what that does is it loops through your matches.
Put the current Match with its ID in if that ID doesn't exist yet.
.putIfAbsent returns the old value which is null if it did not exist.
You then check if there was an item in the map at that ID using the putIfAbsent (2 birds with one stone).
after that it is safe to compare the two dates (one in map and one from iteration - the < is an exams for your comparison method)
if the new one is later then replace the current Match.
And finally in order to get your list you use .getValues()
This will remove duplicate IDs and leave only the latest ones.
Apologies for typos or code errors, this was done on a phone. Please notify me of any errors in the comments.
Java 7 does not have the .putIfAbsent and .replace functionality, but they can be substitued for .contains and .put

Replacing value of a two dimensional java ArrayList

I have two dimensional arrayList, and I want to replace the that is set in the program. The problem is, if i replace the value of arrayList by "ONE", it will work, if I replace it by another value bigger than one, the program enters into a loop. I am using the following syntax:
arrayList.get(index).set(index2,VALUE)
Basically this shouldn't be happening, cause I am not changing anything within the loops, or?
My Questions is WHY? and How to fix it?
the code that is (i assume) producing the problems is:
if(mark.get(index1).get(index2) == 1 && mark.get(i-1).get(j) != 1){
// Replace the value
mark.get(i-1).set(j,1);
flag = true;
}
EDIT: I removed my code, cause it gave the impression I wanted help with the code, i had posted it so that you know what I was talking about. thanks
Got what the problem was! All the initials indexes had a value of ZERO, and I had a condition that was checking if it was not ONE(assuming it will be zero anyway). if i changed it to any other value than ONE then in the next repetitions the condition would have been voided.

Hybrid between features of Queue and Map types

I understand that a queue is a collection type that is accessed through the head and/or tail.
I also understand that a map is a collection type the contains a number of unique keys, which each have an associated value.
What I need, is a map, with a fixed number of values, where the keys will be set once, and will not be changed after they are first set.
The hard part I can't get my head around is getting the values to act as a queue with a fixed length, which can be pushed, without affecting the key.
For example:
Initial collection (newest items at the top):
Key1, Value1
Key2, Value2
Key3, Value3
Collection after adding new value NewValue:
Key1, NewValue
Key2, Value1
Key3, Value2
So, I want the key to stay the same, and be able to add the new value, by pushing the oldest value off the end, and moving all other values further down towards the end.
If a type like this isn't available within the framework, could somebody please recommend a way to implement it.
Thank you!
EDIT:
An example of why I need to do this:
I need to be able to access the values
according to the time period it was
created in.
Example:
Key: 0 will contain a value from today
Key: -1 will contain a value from yesterday
Key: -2 will contain a value from two days ago
etc.
Only one value will be entered every
day, and one value will ALWAYS be
entered every day.
Sounds like you could use:
new LinkedHashMap<Long,V>(initialCapacity, loadFactor, false) {
protected boolean removeEldestEntry(Map.Entry<Long,V> e) {
return size() > MAX_ENTRIES;
}
};
To get or put items in this map you will need to canonicalize your timestamp, e.g., to 00:00:00.000 of the day.
An advantage of this approach is when the assumption that "one value will ALWAYS be entered every day" is violated it won't fail silently.
So, you're really talking about an index into an array.
I'd just wrap an 'ArrayList` in your object.
Your push method would also remove the "oldest" element from the end. You'd define methods such as getToday() and getPriorDay(numDaysBackFromToday)
However, you're using a lot of magic numbers there if you're not actually storing a date or a time with the data. You're hoping that the data has been loaded correctly.
Personally I'd use a timestamp associated with the data in a LinkedHashMap and iterate to find the one you want.
I've rethought my question with regards to the magic numbers, and have decided it'd be easier to use a predefined collection type with positive indexes. Then I'll simply make the push method drop the last item off the end when I reach the maximum number of values I need.
Then I'll get my class to interpret -1 as 1 to get the required value.
Thanks for your help, I was simply over-thinking things.

Problem using if statement with ArrayList

I am using an if statement as shown below,
if(sign.size()==0)
Here sign is of the type ArrayList<Character>
I am trying to add a char to the ArrayList
But its not working. Is there anything wrong with my if statement?
I also tried the same with an ArrayList<doubler>, this time I could get into the if statement.
Is there anything wrong with the if statement?
I am having very difficult time understanding what you are saying, but it sounds like you are trying to figure out how to increase the list capacity. You do not need to manually do this. Simply add items using add() method and the list will re-size itself as appropriate.
Try if(sign.isEmpty()) instead. Also make sure you you're using good code style with {'s where needed. ArrayLists will adjust their own size to accommodate what you put in, so I'm not sure you even need this check.
You commented on an answer and said,
i want to get in the if only if i have 1 char in the array... but i does not get in to the if.... way if i have only one index
If you want to enter the IF only when there is one char, then you'd want
IF(sign.size() == 1){
...some code
}
Otherwise, if you want to enter the IF when size is 0, use isEmpty.
As you said
I want to get in the if only if I have
1 char in the array... but it does not
get in to the if.... what if i have
only one index?
If you are trying to enter the if statement only when there is only one char in the ArrayList then you can use
if(sign.size() == 1){
//your code
}
The condition will only be true when the size of the ArrayList is equal to 1.

Categories

Resources