0

I was writing an algorithm about graph theory in Java, and had the nodes on the graph defined as:

public class Node {
    public String UUID;
    public Set<Node> children;
    // and some other fields & methods

    @Override
    public int hashCode() {
        return UUID.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) return false;
        if (!(obj instanceof Node))return false;
        Node other = (Node)obj;
        return UUID.equals(other.UUID);
    }   
}

The UUID field of any certain node on the graph was guaranteed to be unique (by input dataset), so I planned to store all the nodes in a HashSet<Node> while reading the input dataset and building the adjacency list which was also defined as Set<Node> children in Node class.

However, soon I noticed that I couldn't really get Node instances stored in my HashSet<Node> in an elegant way because Set can't be randomly accessed.

The parentNode-childNode The problem is: I want to get a specific Node instance stored in the HashSet with its specific UUID (thus the same hashCode) because I have to update the adjacency list of each node, WHILE I cannot really use any Set to do this.

I guess I am confused. If I switch to Map<String, Node> and make UUID be the key, it just feels like dumb to define UUID in Node class ( BUT UUID should be a part of the Node logically!)

I've read this post and still believe that java should provide interface to access elements in Set (or at least some of its implementation) since this is not impossible through binary tree, just like C++ STL set.find() did.

Any suggestion on how I should hack this?

SedriX
  • 500
  • 3
  • 10
  • 3
    `Node other = (Node)obj;` -> not safe without checking `instanceof`. – shmosel Jul 17 '17 at 08:04
  • 1
    Using a map is not dumb. It's what you do when you want to access by a specific key. – RealSkeptic Jul 17 '17 at 08:08
  • 1
    BTW, there is nothing dumb in using a `Map` the way you suggest. – Eran Jul 17 '17 at 08:08
  • And another hint: Java has a predefined **UUID** class. Use that one, instead of using raw strings! – GhostCat Jul 17 '17 at 08:09
  • @GhostCat the `hashCode()` method is actually there in plain view. – RealSkeptic Jul 17 '17 at 08:09
  • @Eran Thanks Eran, and I find that should be a typo when I was posting (not in my code editor :) anyway I want to make the comparison between `Node`s to be the comparison between their `UUID`s string value – SedriX Jul 17 '17 at 08:21
  • Uups. Right hashCode() is there. Several findings in just a few lines of code. And another one: do **not** make your fields public! – GhostCat Jul 17 '17 at 08:22
  • @GhostCat Fields are public here because I don't feel like to post their getter and setter too. UUID was String because it was read from an Office Excel `.xlsx` file using Apache POI and not further wrapped yet. Anyway thank your comments. I am a freshman to Java indeed :) – SedriX Jul 17 '17 at 08:36

2 Answers2

0

I switch from HashSet<Node> to Map<String, Node>, where UUID is used as key String, to store all the nodes on the graph, yet still keep the UUID field in Node class for future extension.

It seems really weird that java focus so much on "modeling the mathematical set abstraction", while std::set::find and std::unordered_set::find in C++ can fetch element in set in O(log n) and Log(1)(average) respectively.

Well, my conclusion is: If you want to store some objects in a certain data structure without the requirement to keep them in order, and later fetch specific objects to update, still you should't use java.util.Set. Use java.util.Map instead, even if you have to add some redundant fields or key. You cannot really fetch anything from Set in Java without iterating the whole set.

SedriX
  • 500
  • 3
  • 10
  • It's not weird. A set in Java represents a set of elements, not keys. It doesn't make sense to lookup an element by itself. – shmosel Jul 17 '17 at 16:47
0

If you use HashSet,

  • you could use the clone() (Returns a shallow copy of this HashSet)
  • onthis copy call the retainAll to filter only the node you want.

:)

Ofer Skulsky
  • 685
  • 4
  • 10
  • Making a shallow copy is somewhat too expensive for my case, since I have to repeat fetching & updating one element many times, and I think Map will work for me. Anywhy thanks for your answer, Ofer. – SedriX Jul 17 '17 at 10:03