I'm using List of strings and trying to insert strings to specified indices using
lst.add(index, string);
(lst is of type `List`).
First I initiated the list to 20 spots of null (now lst.size() = 20).
When I'm inserting the first string it's all good : lst.add(1,"Hi") and the list:
[null,Hi,null,...null], lst.size() is still 20
But when I try to add the next strings it extends the list. I mean if I use lst.add(0,"Bye") the list looks like this: [Bye,null,Hi,null,null,...null] and lst.size() = 21 ! Why ?
it added the string "Bye" before the null though it should have replaced it
Any help ? thanks :)
The add() method inserts into the list.
From JavaDoc:
Inserts the specified element at the specified position in this list
(optional operation). Shifts the element currently at that position
(if any) and any subsequent elements to the right (adds one to their
indices).
You want to use the set() method instead.
When you do 'add' it is actually an insert to a list - therefore you would have 21 elements instead of 20 after the add.
A list can be thought as a resizeable array. You shouldn't need to initialise an array with 20 nulls inserted in it.
If you want total control on the size of the collection, simply use array instead of list (String[] instead of List<String>)
Related
so i have an array list that contains strings such as:
ArrayList<String> list = new ArrayList<>();
list.add("bookshelf");
list.add("bookstore");
list.add("library");
list.add("pencil");
Now i wanna search and remove all the strings in the arraylist that contain the word "book" in them. As far as i understand list.remove("book"); will only search for the particular string "book" and not the strings that contain the word "book". How can i solve this?
You can use removeIf like this:
list.removeIf(s -> s.contains("book"));
Note: this answers applies to Java version 7 and below (of course that it will work for higher versions as well but YCF_L's answer is simpler to implement in versions 8 and above).
The requirement is to iterate the list, check every element, and if it answers a certain condition: remove it.
Since this is the case we fall into a risky scenario where we modify the list while iterating it which is problematic because when we remove an element in the list its size changes.
In order to work around this problem we can iterate the list by index from the last element and back until the first one, this way, removing an element at index n will not effect accessing any element at index < n.
I'll leave the implementation details to you in order not to "spoon feed" and destroy your exercise :)
As far as I know, here are steps to remove an element in an ArrayList.
No need to do anything with the target element
Iterate along the array from 1 after the deleted element, to the last element
Copy each element into the location 1 before it
Set the last element to null
Why don't just set the element we want to remove to null? That takes only one step.
Could anyone explain the merit of above scheme? Thanks in advance.
Because these are not the same (let's remove the "c"):
["a", "b", "d", "e"]
["a", "b", null, "d", "e"]
There is a big difference between the removal and the replacement:
The removal changes the indices, removes an element and shifts (affects) the remaining ones. This also changes the size of the list. Ex. the element "d" is accessible at the index 2 (moved from the 3).
The replacement replaces the item and keeps the indices of the elements and the size of the list remains unchanged as well. Ex. the element "d" is accessible at the index 4 (unchanged).
Why don't just set the element we want to remove to null?
"setting" an element to null is not removing an element it's replacing an element.
There's another issue with that approach, if null in a list means the element at that index is "removed" then what if I want to actually store null as an element? how do you distinguish a removed element and an actual null element?
Leverage the remove methods in the List<T> API, don't try to reinvent the wheel as they're as good as they can get.
...because that's how Lists work. Many usecases need this dynamic sizing behaviour, so Java has an interface for the List concept. ArrayList is one of several implementations of List, LinkedList is another.
We already had the behaviour you're describing, the Array - so where you need that behaviour you would use say a String[].
ArrayLists are just like arrays with one difference - they are resizable(it does not matter in this example).
Consider the following array: [ref1,ref2,ref3,ref4] , where ref1:4 are references to some objects. It means that they do not contain the object itself, they only point to the object. Now, if you want to delete ref2 for example by declaring it null that means that it won't point to any object now (ref2 = null) but that does not mean that the reference itself dissapeard.Your new array(ArrayList) will be [ref1,null,ref3,ref4] now. You see? There is a difference between replacement and removal....
I have this code, I can't understand how the code works, how does it remove duplicates with that indexOf and lastIndexOf?
ArrayList<String> lst = new ArrayList<String>();
lst.add("ABC");
lst.add("ABC");
lst.add("ABCD");
lst.add("ABCD");
lst.add("ABCE");
System.out.println("Duplicates List "+lst);
Object[] st = lst.toArray();
for (Object s : st) {
if (lst.indexOf(s) != lst.lastIndexOf(s)) {
lst.remove(lst.lastIndexOf(s));
}
}
System.out.println("Distinct List "+lst);
how does it remove duplicates with that indexOf and lastIndexOf?
if (lst.indexOf(s) != lst.lastIndexOf(s))
The code above takes the index of the first occurrence of s(if it exists otherwise -1) within the list and also takes the index of the last occurrence of s (if it exists otherwise -1) within the list, if both of the indices are the same then there is no duplicate and if they are not the same then we've found a duplicate thus it gets removed from the list.
From the code you're currently working on, we can confirm that the string "ABC" appears twice within the collection, one at index 0 and the other at index 1 thus when this is checked by the if statement we can guarantee that control will go inside the if statement because they're not the same indices(meaning there are at least two occurrences of the string s), likewise the string "ABCD" appears twice within the list at index 1 and 2(note by this time the last occurrence of "ABC" is already removed from the list hence "ABCD" takes the slot of index 1 due to the nature of a list resizing itself) meaning control will once again go inside the if block because they're not the same indices.
Eventually, the last occurrence of s will be removed from the list and the same procedure is repeated for each iteration of the loop.
There are more efficient ways in which you can remove duplicates from a list, and you should look into it as it can improve performance time.
Try throwing a few more print statements in there, I think you'll be able to see for yourself!
for (Object s : st) {
System.out.println(s);
System.out.println(lst.indexOf(s));
System.out.println(lst.lastIndexOf(s));
if (lst.indexOf(s) != lst.lastIndexOf(s)) {
lst.remove(lst.lastIndexOf(s));
}
}
It is a pretty clunky (i.e. inefficient) way to do it1.
How does it work?
Well this predicate:
lst.indexOf(s) != lst.lastIndexOf(s)
is testing to see if there are two (or more) instances of s in the list. The logic is that if the position of the first s and the last s in the list are different, then there must be at least two of them. Then we remove the last instance.
Since we do this for every string in the original list, if there are M instances of a given string in the list, that test will be performed M times for that string, and will succeed M - 1 times and hence remove M - 1 of those instances. At the end, you are left with just one instance of each distinct string; i.e. no duplicates.
1 - It is O(N^2) and it is possible to eliminate duplicates in O(N) with O(N) temporary space. The general approach is as follows:
Create a temporary array to hold the list content, and a HashSet.
For each s in the original list:
If s is not in the set:
add it to the set, and
add it to the temporary array.
Clear the original list.
Add back all elements in the temporary array.
I am currently making a tiny little program that should be able to select a random element i put into the array using a Random of course (For practice purposes) and when a element in the array has been chosen at random. i want to remove this element in the array, so how do you remove a element in a array the easiest way?
Its the only thing i want to know. I got everything else sorted. It's just removing the element it has chosen (the random takes a random number between 0 and the amount of elements in the array, so if it chooses 0, it will take the first element in the array, and so on)
You can use ArrayList which support remove or add function, which actually is an resizable array.
You can't remove an element from an array. You can replace it with some other value that indicates "nothing", null for example.
An easy solution is to convert the array into a list.
list = Arrays.asList(array);
Remove any element from the list and then revert it back to an array using
array = list.toArray();
Hope it helps.
Use List instead of Array, and if you want to stay on Array than there is 2 solution,
Create another Array ignoring your element which you want to delete.
create a List using Array.asList(...) than remove element from list and convert back to Array.
but according to me its better for you as well as java to use List. because List provide a many build-in functions.
In my Android app Java code I have an ArrayList of a custom data type. From what I know about ArrayLists when you perform a ArrayList.remove(location) all items located above location get shifted down by one. But for some reason when I iterate backwards from end to start of the array in order to remove selected items in the array, each time and item is removed all the items below it get shifted up one instead of the normal behavior of the higher items getting shifted down one. So when I remove the first item in the middle of the array, the item at 0 shifts to 1 and 0 becomes null. Is there something in particular that I could have done or a certain situation that would cause this to happen?
I apologize for not being clear about exactly what I was doing. Im not iterating through the ArrayList. but instead I have another List containing all of the items in the original list i need to remove. I perform a Collections.sort on the second list and the iterate from end to start on that second list and on each iteration I perform a ArrayList.remove one the first list with the location read from the second list. therefore the removes go from highest location to lowest which i though would prevent any shifts from occurring of the lower items on each removal. but what i see happening is the items lower than the removed item all getting shifted up to fill in the gap. why is this happening?
If you need to iterate through a list, removing items from the list as you go, try using an Iterator and a while loop. The Iterator interface defines a remove() method that deletes the last item retrieved with next() from the Collection being iterated over.
List list = new ArrayList( );
Iterator iter = list.iterator( );
while ( iter.hasNext( ) )
{
Object item = iter.next( );
if ( shouldDelete( item ) )
{
iter.remove( );
}
}
so when i remove an item somewhere in the middle of the list, the item at 0 moves to 1, and 0 then becomes null. Why is this happening?
That shouldn't happen, something else must be wrong. Please post an SSCCE.
I recommend you to solve it like this however:
firstList.removeAll(secondList);
It seems like you only sort the second list, so I'm not surprised at your outcome. Since the first list is unsorted, you will not be iterating through it in reverse order, and strange shifts can be expected.
Why not instead go through the first list using a list iterator, and if the item is contained in the second list, remove it from the first using the iterator?
Or even better, use the ArrayList#removeAll<Collection<?> c) method.