自制迭代器在Java中的集合

时间:2017-07-04 21:24:21

标签: java iterator set

为了准备我的考试,我正在写一些给我们的旧考试。在其中一个中,我们必须实现EnterpriseNode。一个任务是编写一个遍历Staffmembers的迭代器。我写了函数next()但它无法正常工作。 这是我的代码:

public StaffMemberIterator(HashSet<StaffMember> directSubordinates){
        if(directSubordinates == null) throw new NullPointerException("ofs");
        this.directSubordinates = directSubordinates;
    }


public StaffMember next() {
        if (!this.hasNext()){
            throw new NoSuchElementException("naf");
        }
        ArrayList<StaffMember> subList = new ArrayList<>(directSubordinates);
        StaffMember staffMember = subList.get(position);
        position++;
        return staffMember;
    }

这是错误:

junit.framework.AssertionFailedError: StaffMemberIterator.next() should return the correct next element if there is one available! expected:<Name: Allie, Job: J1> but was:<Name: Lilith, Job: J3>
    at StaffMemberIteratorTest.testIterator(StaffMemberIteratorTest.java:48)

谢谢你们的帮助!

2 个答案:

答案 0 :(得分:1)

正如Klas在评论中所说,HashSet并没有强加任何特定的订单。 TreeSet会根据自然顺序或定义的Comparator强加订单。 HashSet中值的顺序取决于散列函数的结果。

我不确定您的考试问题实际上是在寻找什么,但考虑到您在Java中实现迭代器,实现Iterator<E>接口是有意义的。

示例实施:

import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;

public class StaffIterator implements Iterator<StaffMember> {

    private final StaffMember[] staffMembers;
    private int index;

    public StaffIterator(Set<StaffMember> staffMembers) {
        this.staffMembers = staffMembers.toArray(new StaffMember[staffMembers.size()]);
        index = 0;
    }

    @Override
    public boolean hasNext() {
        return index < staffMembers.length;
    }

    @Override
    public StaffMember next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        return staffMembers[index++];
    }

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

注意:由于AbstractCollection.toArray(T[] a)遍历Collection以填充数组,因此效率不高。但它肯定比每Collection次呼叫将ArrayList复制到next()更有效。

答案 1 :(得分:1)

尝试使用LinkedHashSet代替HashSet

如果您没有得到您期望的工作人员,那是因为HashSet不保留元素的插入顺序。如Javadocs中所述:

  

此类实现Set接口,由哈希表(实际上是HashMap实例)支持。 无法保证集合的迭代顺序;特别是,它不保证订单会随着时间的推移保持不变。 此类允许null元素。

另一方面,

LinkedHashSet保留插入顺序。正如Javadocs中引用的那样:

  

Set接口的哈希表和链表实现,具有可预测的迭代顺序。此实现与HashSet的不同之处在于它维护了一个贯穿其所有条目的双向链表。 此链接列表定义迭代排序,即元素插入集合(插入顺序)的顺序。 请注意,如果元素不影响插入顺序被重新插入集合中。