1

I am creating a partially ordered set as an abstract data type in java, and I have to make an iterator version of the set of numbers, and an iterator for the relations. Now for the elements, I've used HashSet of integer, and for the relations, I've used an ArrayList of pairs (pairs is a class I created that takes 2 ints as parameter which basically is like (x, y)). I need to make 2 iterators, one for s and one for r, but they have to follow a certain ordering, 1. if (x, y) belong to R, then the iterator of s should return x before it returns y 2. if (x, y) and (y, z) belong to R, then iterator of r should return (x, y) before it returns (y, z)

I made a helper method that check first for to check if the element n in the set is the first element in a pair then it returns it, but I cant seem to check if it is second element, how can I check for the first element if it is returned or not?

Here is my code:

private class IntGenerator implements Iterator {
        private Iterator<Integer> i;


        public IntGenerator () {
            i = S.iterator();
        }

        public boolean hasNext() {
            return i.hasNext();
        }

        public Object next() {
            int n = i.next();

            for (Pair p : R) {
                if (isInFirstElmPair(p,  n)) return n;
                else (isInSecondElmPair(p, n)) {
                                    // should check for the first element
                                    // if it was returned or not
                }
            }
        }

        public void remove() { throw new UnsupportedOperationException(); }
    }

I would really appreciate any kind of help, or hint in this code. Thanks

EDIT:

Okay, I've wrote the code to it after adding a new set which will hold the returned elements, and this is what I wrote:

Set<Integer> returnedNumbers = new HashSet<Integer> ();
public Object next() {
            int n = i.next();

            for (Pair p : R) {
                if (isInSecondElmPair(p, n)) {
                    if (returnedNumbers.contains(p.getFirstElm())) {
                        returnedNumbers.add(n);
                        return n;
                    }else{
                        returnedNumbers.add(p.getFirstElm());
                        return p.getFirstElm();
                    }
                }else{
                    returnedNumbers.add(n);
                    return n;
                }
            }
        }

Is this code correct? Also, eclipse seems to give me an error telling me I need to return a value outside the loop, but I already returned inside for every case why does it need more? Appreciate the help

hakuna matata
  • 3,243
  • 13
  • 56
  • 93
  • 1
    I don't fully understand the question, but I have some notes. If I get you right, the code you supplied is the implementation of 's' (please use a clearer naming convention next time). Now it looks possible that a number from the set is not returned by its iterator, for example when it is returned before its corresponding 'first elements' in any pairs. Am I right? Is this intended? Moreover, this won't scale too lovely in my opinion, you iterate through a lot of things to retrieve one umber, and if I'm not mistaken, r may grow very big. Unfortunately I cannot provide a better solution yet... – Vincent Mar 22 '12 at 23:07
  • Regarding the edit itself: opening a new question is usually better than editing one where you already accepted an answer. Not many people look at already answered questions unless they have the same problem specified in the title. As for the edit content: What does `next` return if `R` is empty? (You may think that it is not, but eclipse does not know that.) – arne.b Mar 23 '12 at 09:53
  • as for the correctness: write a test or main method adding a few pairs and see whether it fits, for a start (would be great if your element type were not limited to integer, so that you can test it with elements that do not have a natural ordering known to java). For a non-trivial test with integer pairs, try, for example: 1-0, 2-0, 4-3, 5-1, 5-4, 3-2 (to make it a bit meaner, one could add 5-0 before the others). The element iterator should then return 5-4-3-2-0 in this order and the 1 anywhere in between. Yes, I do find this a very interesting problem. :-) – arne.b Mar 23 '12 at 10:02
  • R is never empty, becuase if I add an element to S, it will add a reflexive pair to R, (n, n), that's why I'm assuming R is never empty – hakuna matata Mar 23 '12 at 10:38

1 Answers1

1

Well, to check if a value was previously returned, you of course need to keep track of all values that were returned previously.

So in your iterator, you could define

Set<Integer> previouslyReturned = new HashSet<Integer>();

and then, before returning it in your for loop, add it there:

if (isInFirstElmPair(p,  n)) {
    previouslyReturned.add(n);
    return n;
}
else (isInSecondElmPair(p, n)) {
    if (previouslyReturned.contains(n) {
        // do one thing
    } else {
        // do another thing
    }
}

This way, however, you are constructing a set of s in the order in which it shall be returned inside the iterator. It would make sense to create this once (consider a LinkedHashSet), keep it somewhere else and iterate over it.

Generally I am not sure that this approach will lead to what you want. Do you know anything about theorder of elements in S and R? If the iteration order is arbitrary (i.e. because relations were added in unpredictable order) then the iterator will first return the first half of the first relation pair, even if that element is in the second half of another pair. Do you have to use an element HashSet and a relation List?

arne.b
  • 4,212
  • 2
  • 25
  • 44
  • Having another data structure to hold the returned elements seems to be a good idea, I will try it and post the results when I do it. Thanks arne.b – hakuna matata Mar 23 '12 at 09:08