How can
Iteratorcan using in set?
Like you are using it.
How can get the values โโone by one through an iterator?
Your code is doing that.
Is iterator changing set into like list which ordered data structure?
No.
The thing that you are missing is what "unordered" means. It means that the order in which the (set's) elements are returned is not predictable1, and not specified in the javadocs. However each element will be returned once and (since the elements of a set are unique!) only once for the iteration.
1 - Actually, this is not strictly true. If you have enough information about the element class, the element values, how they were created and how / when they were added to the HashSet, AND you analyze the specific HashSet implementation ... it is possible that you CAN predict what the iteration order is going to be. For example if you create a HashSet<Integer> and add 1, 2, 3, 4, ... to it, you will see a clear (and repeatable) pattern when you iterate the elements. This is in part due to the way that Integer.hashCode() is specified.
How can Iterator can using in set(java)? - Stack Overflow
How do I iterate and modify Java Sets? - Stack Overflow
java - How to Iterate over a Set/HashSet without an Iterator? - Stack Overflow
How to use Iterator on a set
You get a NoSuchElementException because you call next on an iterator that has no next element. Call hasNext first, to ensure that the iterator is not empty, before calling next.
Your first code snippet does not compile because you call getPositionX twice, once on your double test.
How can
Iteratorcan using in set?
Like you are using it.
How can get the values โโone by one through an iterator?
Your code is doing that.
Is iterator changing set into like list which ordered data structure?
No.
The thing that you are missing is what "unordered" means. It means that the order in which the (set's) elements are returned is not predictable1, and not specified in the javadocs. However each element will be returned once and (since the elements of a set are unique!) only once for the iteration.
1 - Actually, this is not strictly true. If you have enough information about the element class, the element values, how they were created and how / when they were added to the HashSet, AND you analyze the specific HashSet implementation ... it is possible that you CAN predict what the iteration order is going to be. For example if you create a HashSet<Integer> and add 1, 2, 3, 4, ... to it, you will see a clear (and repeatable) pattern when you iterate the elements. This is in part due to the way that Integer.hashCode() is specified.
Referring to the documentation, we see that:
Iterator<E> iterator()
Returns an iterator over the elements in this collection. There are no guarantees concerning the order in which the elements are returned (unless this collection is an instance of some class that provides a guarantee).
Since there are no guarantees concerning the order in which the elements are returned for iterator, it is not a problem for iterator to apply to Set, which is unordered.
Further, it is not changing the Set into a List
You can safely remove from a set during iteration with an Iterator object; attempting to modify a set through its API while iterating will break the iterator. the Set class provides an iterator through getIterator().
however, Integer objects are immutable; my strategy would be to iterate through the set and for each Integer i, add i+1 to some new temporary set. When you are finished iterating, remove all the elements from the original set and add all the elements of the new temporary set.
Set<Integer> s; //contains your Integers
...
Set<Integer> temp = new Set<Integer>();
for(Integer i : s)
temp.add(i+1);
s.clear();
s.addAll(temp);
You can do what you want if you use an iterator object to go over the elements in your set. You can remove them on the go an it's ok. However removing them while in a for loop (either "standard", of the for each kind) will get you in trouble:
Set<Integer> set = new TreeSet<Integer>();
set.add(1);
set.add(2);
set.add(3);
//good way:
Iterator<Integer> iterator = set.iterator();
while(iterator.hasNext()) {
Integer setElement = iterator.next();
if(setElement==2) {
iterator.remove();
}
}
//bad way:
for(Integer setElement:set) {
if(setElement==2) {
//might work or might throw exception, Java calls it indefined behaviour:
set.remove(setElement);
}
}
As per @mrgloom's comment, here are more details as to why the "bad" way described above is, well... bad :
Without getting into too much details about how Java implements this, at a high level, we can say that the "bad" way is bad because it is clearly stipulated as such in the Java docs:
https://docs.oracle.com/javase/8/docs/api/java/util/ConcurrentModificationException.html
stipulate, amongst others, that (emphasis mine):
"For example, it is not generally permissible for one thread to modify a Collection while another thread is iterating over it. In general, the results of the iteration are undefined under these circumstances. Some Iterator implementations (including those of all the general purpose collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected" (...)
"Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception."
To go more into details: an object that can be used in a forEach loop needs to implement the "java.lang.Iterable" interface (javadoc here). This produces an Iterator (via the "Iterator" method found in this interface), which is instantiated on demand, and will contain internally a reference to the Iterable object from which it was created. However, when an Iterable object is used in a forEach loop, the instance of this iterator is hidden to the user (you cannot access it yourself in any way).
This, coupled with the fact that an Iterator is pretty stateful, i.e. in order to do its magic and have coherent responses for its "next" and "hasNext" methods it needs that the backing object is not changed by something else than the iterator itself while it's iterating, makes it so that it will throw an exception as soon as it detects that something changed in the backing object while it is iterating over it.
Java calls this "fail-fast" iteration: i.e. there are some actions, usually those that modify an Iterable instance (while an Iterator is iterating over it). The "fail" part of the "fail-fast" notion refers to the ability of an Iterator to detect when such "fail" actions happen. The "fast" part of the "fail-fast" (and, which in my opinion should be called "best-effort-fast"), will terminate the iteration via ConcurrentModificationException as soon as it can detect that a "fail" action has happen.
You can use an enhanced for loop:
Set<String> set = new HashSet<String>();
//populate set
for (String s : set) {
System.out.println(s);
}
Or with Java 8:
set.forEach(System.out::println);
There are at least six additional ways to iterate over a set. The following are known to me:
Method 1
// Obsolete Collection
Enumeration e = new Vector(movies).elements();
while (e.hasMoreElements()) {
System.out.println(e.nextElement());
}
Method 2
for (String movie : movies) {
System.out.println(movie);
}
Method 3
String[] movieArray = movies.toArray(new String[movies.size()]);
for (int i = 0; i < movieArray.length; i++) {
System.out.println(movieArray[i]);
}
Method 4
// Supported in Java 8 and above
movies.stream().forEach((movie) -> {
System.out.println(movie);
});
Method 5
// Supported in Java 8 and above
movies.stream().forEach(movie -> System.out.println(movie));
Method 6
// Supported in Java 8 and above
movies.stream().forEach(System.out::println);
This is the HashSet which I used for my examples:
Set<String> movies = new HashSet<>();
movies.add("Avatar");
movies.add("The Lord of the Rings");
movies.add("Titanic");
I was trying to get a method of a object in a LinkedHashSet, but I get errors. Can Someone please explain why this doesn't work?
This doesn't work
Iterator<className> it = model.getLinkedHashSet().iterator();
while(it.hasNext()) {
double test = it.next().getPositionX();
rectangle = new Rectangle(test,0,100 , 100);}This works
Iterator<className> it = model.getLinkedHashSet().iterator();
while(it.hasNext()) {
className element = it.next();
test = element.getPositionX();
rectangle = new Rectangle(test,0,100 , 100);}The error I get is:
Exception in Application start method java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389) at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767) Caused by: java.lang.RuntimeException: Exception in Application start method at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917) at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$154(LauncherImpl.java:182) at java.lang.Thread.run(Thread.java:748) Caused by: java.util.NoSuchElementException at java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:721) at java.util.LinkedHashMap$LinkedKeyIterator.next(LinkedHashMap.java:742) at view.blabla.BlaBlaPresenter.updateView(BlaBlaPresenter.java:122) at view.blabla.BlaBlaPresenter.<init>(BlaBlaPresenter.java:27) at Main.start(Main.java:26) at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(LauncherImpl.java:863) at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$174(PlatformImpl.java:326) at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295) at java.security.AccessController.doPrivileged(Native Method) at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294) at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95) at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177) ... 1 more Exception running application Main
You get a NoSuchElementException because you call next on an iterator that has no next element. Call hasNext first, to ensure that the iterator is not empty, before calling next.
Your first code snippet does not compile because you call getPositionX twice, once on your double test.
Why not just use a for-each loop?
for (ClassName each : model) {
rectangle = new rectangle(each.getPositionX(), 0, 100, 100);
}
public Set<B> getBs(){
Iterator<A> iterator = myFunc.iterator();
Set<B> result = new HashSet<B>();
while (iterator.hasNext()) {
result.add((B) iterator.next();
}
return result;
}
But of course, it will fail if all the As returned by the iterator are not Bs.
If you want to filter the iterator, then use instanceof:
public Set<B> getBs(){
Iterator<A> iterator = myFunc.iterator();
Set<B> result = new HashSet<B>();
while (iterator.hasNext()) {
A a = iterator.next();
if (a instanceof B) {
result.add((B) iterator.next();
}
}
return result;
}
Using Guava, the above can be reduced to
return Sets.newHashSet(Iterators.filter(myFunc.iterator(), B.class));
I'm still not 100% sure what you want, but check this out and see:
public static void main(String[] args) {
final Iterator<?> it = Arrays.asList(new Object[] {"a", "b", "c"}).iterator();
System.out.println(setFromIterator(it));
}
public static Set<String> setFromIterator(Iterator<?> it) {
final Set<String> s = new HashSet<String>();
while (it.hasNext()) s.add(it.next().toString());
return s;
}