【问题标题】:Selfmade iterator over a set in Java在Java中的集合上的自制迭代器
【发布时间】:2017-12-08 09:50:19
【问题描述】:

为了准备我的考试,我正在写一些给我们的旧考试。在其中一个中,我们必须实现一个 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)

谢谢大家的帮助!

【问题讨论】:

  • 所以您有 JUnit 测试,但没有尽可能多地利用它们?您是否尝试过调试以查看您的迭代器做了什么? hasNext() 是如何工作的?有很多问题,但需要处理的代码并不多。
  • 我没有看到任何对集合成员施加特定顺序的东西。
  • 欢迎来到 Stack Overflow!看来您需要学习使用调试器。请帮助自己一些complementary debugging techniques。如果您之后仍有问题,请随时返回 Minimal, Complete and Verifiable Example 来证明您的问题。

标签: java iterator set


【解决方案1】:

尝试使用LinkedHashSet 而不是HashSet

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

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

LinkedHashSet 另一方面,保留插入顺序。正如 Javadocs 中所引用的:

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

【讨论】:

    【解决方案2】:

    正如 Klas 在评论中所说,HashSet 不会强加任何特定顺序。 TreeSet 将基于自然排序或定义的 Comparator 施加顺序。 HashSet 中值的顺序将取决于散列函数的结果。

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

    示例实现:

    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) 会遍历集合以填充数组。但它肯定比每次调用 next() 时将 Collection 复制到 ArrayList 更有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-17
      • 2013-10-10
      • 2010-10-04
      • 1970-01-01
      • 2011-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多