I have a scenario that I am iterating over a set using iterator. Now I want to remove 1st element while my iterator is on 2nd element. How can I do it. I know Set is unordered and there is nothing like first or second element but my question is I want to remove an element which is not being currently returned by Iterator.next
I dont want to convert this set to list and using listIterator.
I dont want to collect all objects to be removed in other set and call remove all
I cant store it and remove after the iteration
sample code.
Set<MyObject> mySet = new HashSet<MyObject>();
mySet.add(MyObject1);
mySet.add(MyObject2);
...
Iterator itr = mySet.iterator();
while(itr.hasNext())
{
// Now iterator is at second element and I want to remove first element
}
Given the constraints as you have stated them, I don't think that there is solution to the problem.
The Iterator.remove() method will only remove the "current" element.
You have excluded "remembering" objects and removing them from the HashSet in a second pass / phase.
Schemes that involve using two iterators simultaneously and removing using one of them will result in CCMEs on the second one.
The three approaches that you suggested (but then excluded) would all work. I think the 2nd one would be the most performant.
Another idea would be to implement a new hash table-based Set type which has an Iterator with an extra remove operation. (You could start with the source code of HashSet etcetera, rename the class and then modify it to do what you need.)
Set.iterator() returns a java.lang.Iterator. This iterator only provides methods to remove the current element and to iterate forward.
So if you don't want to convert your set, using only Iterator you cannot remove the previous element.
What you can do for example is that you collect the elements you want to remove, and after you iterated through the whole set, you remove the collected elements after, e.g. with Set.removeAll(removableCollection):
List<MyObject> removableList = new ArrayList<>();
MyObject previous;
Iterator<MyObject> itr = mySet.iterator();
while (itr.hasNext()) {
MyObject current = itr.next();
// If you find you want to remove the previous element:
if (someCondition)
removableList.add(previous);
previous = current;
}
mySet.removeAll(removeableList);
HashSet is unordered and javadoc clearly states that Iterator's remove method Removes from the underlying collection the last element returned by this iterator (optional operation). So the answer is no through an iterator.Since HashSet contains unique elements,you can use Set.remove(Object) after traversing the first element,in thios case you dont even need to go to the 2nd element
HashSet<K> hs;// you HashSet containing unique elements
if(!hs.isEmpty())
{
hs.remove(hs.iterator().next());
}
Just remember HashSet is unordered and there is no such thing as 1st or 2nd element
Alternately,you should use LinkedHashSet which gives you an ordered Set based on insertion order
Related
I want to iterate over a Set and if some condition meet I want to add elements to it.
While I am doing this, I am getting "ConcurrentModificationException".
When I looked for the answer, I found that in case of listIterator we have add() and remove() method but I can't use list as I also have to take care of duplicates.
Please suggest a way to achieve this.
Edit:
int[] A = {1,2,3,4,5,10,6,7,9};
Set<Integer> s = new HashSet<>();
s.add(1);
Iterator i = s.iterator();
while(i.hasNext()){
int temp = i.next();
int x = next element of array A;
if(x%2==0){
s.add(temp*x);
}
}
But it is throwing ConcurrentModificationException.
How to iterate over Set and add elements to it in java?
It cannot be done. Certainly, not with a HashSet or TreeSet. You will probably need to find an alternative way of coding your algorithm that doesn't rely on doing that.
The normal solution is to create a temporary list, add elements to that list, then when you have finished iterating use addAll to add the list elements to the set. But that won't work here because you appear to want your iterator to see the new elements that you have added.
A second approach would be use a ConcurrentHashMap and Collections::newSetFromMap instead of a HashSet. Iterating a concurrent collection won't give a ConcurrentModificationException. However, the flipside is that there are no guarantees that the iterator will see all of the elements that were added during the iteration. So this probably wouldn't work (reliably) for your example.
I'm working with a big set of data and using lists.
I'm using list iterators to run through the linked list, so i came across a problem, i have to get the next element of next element.
i dont want to get so high specially working with a set with 28k data.
So, using list iterator, theres a way to get the next element of next?
like this:
ListIterator<type> ITERATOR = mylist.listIterator()
while(ITERATOR.hasnext()){
ITERATOR.next().next()??
}
Every loop of the while will give you 2 objects and they will change each loop.
ListIterator<type> ITERATOR = mylist.listIterator()
while(ITERATOR.hasnext()){
Object first= ITERATOR.next();
if(ITERATOR.hasNext())
Object second= ITERATOR.next();
}
Is it possible to remove an object other than the current when iterating?
List<GameObjects> gameObjects = new ArrayList<GameObjects>();
ListIterator<GameObject> iterator = gameObjects.listIterator();
while (iterator.hasNext()) {
iterator.next().update();
// Here I would like to do gameObjects.remove(other_object_in_gameObjects);
}
Obviously that's not allowed. But can an Iterator do it somehow? Or is it not doable at all?
Don't know what other_object_in_gameObjects is, but you can create a temp List recording the list items that needs to be deleted, and after the iteration remove all the items in the tempList that are also in gameObjects.
You might look into using the Guava library. There is an Iterables.removeIf method that allows you to remove all objects from a list that match your criteria.
There's an example of usage at this other SO question.
So i know how to iterate through a whole linkedhashmap from the beginning, but what if I want to only link through a certain portion from it? IE: i want to start from the end and go only 4 elements back. How would I do that and is it possible?
What you are searching for is a ListIterator which would allow you to iterate backwards in a list. Unfortunately, LinkedHashMap does not hold a reference towards the previous element, and thus does not provide this iterator.
So, you end up with two solutions. One, you implement the method to find the X last elements: you hold, let's say an array (a circular buffer) of size X and keep there the last X elements you have seen. This solution is rather inefficient if you call this method frequently and for X much smaller than the size of your map.
A second solution is to keep a HashMap instead of a LinkedHashMap and an extra List to maintain the insertion order. E.g. an ArrayList or a LinkedList which provide a ListIterator and thus, backwards iteration.
You could use the ListIterator for this, by doing something like this.
List list = new ArrayList<>(map.keySet());
ListIterator li = list.listIterator(list.size());
while (li.hasPrevious()) {
System.out.println(map.get(li.previous()));
}
Since the LinkedHashMap maintains the order, you could simply create a list from the keys which are going to be in order as well. Get a ListIterator from the last index, so that you can traverse backwards having a counter(which I've not shown) to iterator till the no. of elements required.
You have to extend standard implementation and override methods that return appropriate iterator to your own.
Iterator<K> newKeyIterator() { return new KeyIterator(); }
Iterator<V> newValueIterator() { return new ValueIterator(); }
Iterator<Map.Entry<K,V>> newEntryIterator() { return new EntryIterator(); }
LinkedHashMap.Entry is a doubly linked list, so you can go forward and backward as well.
LinkedHashMap.LinkedHashIterator is a base iterator for LinkedHashMap. Make what you need based on it.
I have a question regarding the iterator behavior in Java.
I have a call such as this:
myIterable.iterator().hasNext()
If this call returns true, can I be sure that the collection has at least two elements?
From the Java API specification, I could only find out that true means there is one more element to go which can be reached by next(). But what happens if the pointer is at the very beginning (meaning whether the hasNext() can recognize the first element separately)
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Iterator.html
it says true if the iteration has more elements. But more element could also mean the very first one?
[Edit]
How can I know whether the iterator has exactly two elements to iterate through? Of course, I can iterate and count, but I can't go back or iterate twice or clone the iterator in my case, this is an Hadoop iterator.
it can mean the first one. You can only be sure that it has more than zero element
hasNext() returning true or false makes you able to discern between zero items and one-or-more (at the start of the iteration that is).
You want to know whether it has two-or-more, without starting the iteration. I think, basically, you can not. Exposing that information is more than an iterator has to do: make available the next and only the next item (and information about whether this item exists).
Possibly, the iterator itself doesn't even have that knowledge yet!
But of course you are free to memorize the items you already took out of the list. Then you could use them later, once you know there's actually two or more items in the list.
If you need to pass the iterator to other code, you could write your own class that implements iterator, internally remembers the first two items as member variables and hands out those first, then continues to iterate over the rest of the items in the original iterator (if there's any more left) - a reference to the original iterator therefore also needs to be stored in your custom made iterator
Java iterators are positioned before the fist element. What your expression myIterable.iterator().hasNext() shows is that there is at least one element.
hasNext tells you there is another element accessible with next().
So it just mean you have at least one element.
If myIterable.iterator().hasNext() returns true it means there is at least one element and you can use next() to access that.
How can I know whether the iterator has exactly two elements to iteratte through? Of course, I can iterate and count, but I can't go back or iterate twice or clone the iterator in my case, this is hadoop iterable.
There is no way to do this. Maybe an iterator is wrong for your scenario.
No. If hasNext() returns true means, that collection having atleast one element because the origin position of iterator should before the first element.
List l = new ArrayList();
l.add(1);
Iterator it = l.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
Result will be 1 because origin position of iterator should before the first element. When we check it.hasNext() for the first time, it will return true because it is having one element. Then, print the element using it.next(). Now only, iterator in the first position. When we check it.hasNext() for the second time, it will return false.
In the iterator, it has a field named cursor.This cursor init value is the collection object size.When you call the method next(), it will --. The method hasNext() check the cursor is equals to zero.Its zero return false, else return true.
But the list and map is not the same, their difference is the concrete realization, the original is the same.List check size, map check end node.