开发者

Building a custom iterator

I am making this class which is a custom Map based off a hash map. I have an add method where if you add an object the object will b开发者_JAVA百科e the key, and its value will be 1 if the object is not currently in the list. However if you add object that is currently in the list its value will be bumped up by 1. So if I added 10 strings which were all the same, the key would be that string and the value will be 10. I understand in practice when I iterate through the map, there is actually only one object to iterate, however, I am trying to create a inner class that will define an iterator that will iterate the same object however many times its value is. I can do this by simply using for loops to construct an appropriate ArrayList and just create an iterator for that, but that is too inefficient. Is there an easy or more efficient way of doing this?


You can do it with two variables:

private T nextObj = null;
private int times = 0;

T next(){
    if(times==0){
        // get the next object and set the times variable to it's value in the hashmap
    }
    times--;
    return nextObj;   
}


You could use nCopies from the collections API. This will create a list with only one reference so it will be efficient. Then just return that Lists iterator. No need to create an inner class.

Assuming your Map<String, Integer> instance variable is called map, you could do the following:

Iterator<String> customIteratorForKey(String key) {
    return Collections.nCopies(map.get(key), key).iterator();
}


It sounds like you're implementing a multiset or bag: a set that counts each unique element. Since this is a school project, I'll give some pointers on how to do it instead of providing code. Try your luck with it and refine your question if you get stuck.

When I create a new collection type that uses another collection behind it, I typically do the same thing when building the iterator.

  1. Bag.Iterator's constructor would initialize itself with an iterator from the Map.
  2. As dtech showed above, the iterator needs to track the current object it is counting and the number of times it should return it.
  3. next() needs to get the next object at the start and once the current object runs out of counts.
  4. hasNext() must do the same thing without actually decreasing the count or grabbing the next object.


I finally figured it out. Here is my solution. Thanks to everyone who responded and gave me pointers.

    private int times = 0;
    private boolean flag = true;

    Iterator<Entry<T, Integer>> it = Bag.entrySet().iterator();
    private Entry<T, Integer> t = it.next();
    private int value = t.getValue();
    private T nextObj = t.getKey();

    public boolean hasNext() {
        if (times > 0) {
            return true;
        }
        return it.hasNext();
    }


    public T next() {
        if (this.hasNext() == false) {
            throw new NoSuchElementException();
        }
        if (times == 0 && flag == true) {
            times = value;
            flag = false;
        }
        if (times == 0 && flag == false) {
            t = it.next();
            value = t.getValue();
            nextObj = t.getKey();
            times = value;
        }
        times--;
        return nextObj;
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜