The Particle class does not have explicit implementations of equals and hashCode (i didn't do anything :/), do you meant that I can not modify parameters of Objects inside HashSet?
A Java Set enforces uniqueness of elements. Every object added is compared with existing objects to ensure it is not a duplicate.
HashSet does this using the hashCode
and equals
methods of objects to ask them whether they are the same as each other. You can modify fields of objects inside HashSets, but you must not modify any fields that you use in computing the hashCode or testing equality, because that will break/confuse the set.
Since you have not overridden the hashCode
and equals
methods, the default implementations simply test for object "identity": is this the same object? In that case, two created objects with equal values are treated as separate, and both can be added to a single HashSet. Since the fields are not even looked at, you can safely modify any of them without breaking the set.
So it looks like HashSet gives out elements at random. Is it normal?
Yes. A HashSet gives no guarantee as to the order of the elements, and the order will not even remain stable over time. (Internally it orders objects by some of the bits of their hashCodes, giving a difficult-to-predict and effectively random order. When a set grows, it starts looking at more bits of the hashCodes to efficiently determine uniqueness, causing them to rearrange randomly again.) If you really need to enforce order of a Set you can use a LinkedHashSet instead.
However, using a Set at all is probably wasted effort in your application. Instead of Set and HashSet, use List and ArrayList. A List is much simpler and guarantees predictable iteration order: elements are iterated in the order they were added. A List is faster than a Set too, since it doesn't expend effort trying to prevent equal objects from being added twice.
Also no idea what are multiple threads, so unlikely I'm doing that.
As a simple analogy, a thread is an instruction pointer that runs around through the code. (Imagine a finger pointing at a currently executing line of code.) It is what steps through methods, statements, loops, etc, and executes them. You always have at least one thread, otherwise your program wouldn't be running at all. You can create any number of threads and set them running around your program all at once. On a multi-CPU system, these threads can be executed truly simultaneously, one on each CPU. However, you can also have more threads than CPUs, in which case CPUs will take turns executing threads (changing to a different thread every 10 milliseconds or so) to make them seem simultaneous.
And why adding print makes it more systematic?
The only reason I can think of is that you are modifying shared data from multiple threads. Threads are essentially blind to each other, by which I mean they do not naturally try to cooperate. This causes two problems: (1) if two threads try to change data simultaneously, the data can be corrupted and end up with a value that is not correct for either thread; (2) threads might not notice if another thread has changed some variables, because any thread can assume that variables have the same values they were previously set to by that thread.
To make multithreading safe, it is necessary to add some synchronization around any changing data which is shared between threads.
If your set of particles is being used from multiple threads without synchronization, it is possible for the set to be corrupted, and/or for changes in some of the values to not be seen by other threads. The effect of adding a print statement is that it accesses a shared, properly synchronized resource (the output stream to the console) so it causes a happens-before relationship between threads doing the printing, that ensures prior changes are seen, which fixes problem (2), although it is a very sloppy substitute for explicit synchronization.
You could be using multiple threads unintentionally. For example, creating a graphical user interface creates a thread which is used to handle input events. From then on, you should either switch to that thread and do all your program's work on it, or add synchronization around any shared changing data.
If you're sure you're not editing data from multiple threads, I can't see how the print statement could possibly make any difference. (Perhaps it didn't make a difference, and the only confusion was the mis-assumption about the stability of the HashSet.)