【问题标题】:Java iteratorJava 迭代器
【发布时间】:2010-10-28 01:15:10
【问题描述】:

我是新手,我有一个问题。

我有一张地图。我必须遍历地图并构建迭代器。

例子:

public Iterable<Test> getTests(Map<String, Test> testMap,
    Set<String> strings)
{
    //loop tru the set of strings and build iterator.
    for(final String test1 : strings)
    {

       Test test = testMap.get(test1);

       //build a iterator. not a list.
    }

    return iterator
}

我该怎么做?

【问题讨论】:

  • 你能澄清一下吗?
  • 您的问题表明您要构建一个迭代器,但 getTests() 的返回值返回一个 Iterable。它是哪一个?您能否准确说明迭代 getTests() 返回的值的预期行为是什么?

标签: java map iterator


【解决方案1】:

首先,您的方法返回的是Iterable,而不是Iterator。 Map、Set 和 List 都实现了 Iterable,所以它可能比你想象的要容易。

其次,Iterable 只是一个具有iterator() 方法的类,该方法返回Iterator。

所以我会简单地构建一个List 的结果然后返回它。如果你真的想返回Iterator,我会改为在列表中调用iterator() 并返回那个。

【讨论】:

  • Map 没有实现 Iterable。
【解决方案2】:

跳过你的 Iterator/Iterable 混淆(Iterable 基本上是一个 Iterator 工厂......所以你需要以任何方式编写一个 Iterator),我认为你的意思是这样的:

Iterator<Test> getTests(final Map<String,Test> testMap, final Set<String> strings) {
    return new Iterator<Test>() {
      private final Iterator<String> keyIter = strings.iterator();
      private String lastKey;
      public boolean hasNext() { return keyIter.hasNext(); }
      public Test next() { lastKey = keyIter.next(); return testMap.get(lastKey); }
      public void remove() { testMap.remove(lastKey); }
    };
  }

如果你想返回一个 Iterable,那么,它必须是那些的工厂:

Iterable<Test> getTests(final Map<String,Test> testMap, final Set<String> strings) {
    return new Iterable<Test>() {
        public Iterator<Test> iterator() {
            return new Iterator<Test>() {
                private final Iterator<String> keyIter = strings.iterator();
                private String lastKey;
                public boolean hasNext() { return keyIter.hasNext(); }
                public Test next() { lastKey = keyIter.next(); return testMap.get(lastKey); }
                public void remove() { testMap.remove(lastKey); }
              };
        }
    };
}

为了额外的功劳,您可以参数化这个方法本身,并有一种通用的方法来迭代地图中的选择:

Map<String, Action> map;
Set<String> keys;
for (Action x : filterMap(map, keys)) {
}

【讨论】:

  • 懒惰的迭代器方式......我想到了,但懒得真正写它。 :P
  • remove() 可能应该从地图中删除测试(或者抛出 UnsupportedOperationException)。它不应该修改传入的 Set。事实上,您几乎可以肯定地复制传入的 Set。
  • 是的,我试图变得太聪明,可能不应该尝试支持 remove()。我认为将复制传入的集合作为调用者的责任是公平的。在不知道这实际上将如何使用的情况下,很难说,但如果结果只是用于快速循环地图一次,那么复制键就太过分了。
【解决方案3】:

由于Collection 扩展了Iterable,正确的解决方案是将测试添加到某种集合中,例如ArrayList。

Collection<Test> tests = new ArrayList<Test>();
for (String key : strings) {
  Test t = testMap.get(key);
  if (t != null)
    tests.add(t);
}
return tests;

【讨论】:

    【解决方案4】:

    如果你想真正返回 Iterable 最简单的方法是这样

    public Iterable<Test> getTests(Map<String, Test> testMap, Set<String> strings)
    {
       testMap = new HashMap<String, Test>(testMap);
       testMap.keySet().retainAll(strings);
       return testMap.values();
    }
    

    如果要返回迭代器,请将最后一行替换为

    return testMap.values().iterator();
    

    如果您不关心对传入映射的修改,请跳过初始临时映射构建。

    编辑: 在没有它的 Map 界面上删除了对克隆的使用。

    【讨论】:

    • Map 没有公共的 clone() 方法,是吗?
    • 地图界面并不要求它是可克隆的。所以假设传入的 testMap 有一个公共的 clone() 是不安全的。
    【解决方案5】:

    作为一个在黑暗中的刺,你可能正在寻找的是Map.entrySet.iterator()。它允许您遍历地图的条目。

    注意:我知道这不是对 OP 问题的答案,但这是我在回答他们实际寻找的问题时的猜​​测。如果这个猜测结果是错误的,我会再次删除这个答案,以免引起人们的困惑。

    【讨论】:

      【解决方案6】:

      Iterable 与 Iterator 不同。 Iterable 是您可以迭代的东西,例如 List。您为此使用迭代器。您的问题不清楚您想从 getTests() 返回什么。

      最好的办法是创建一个 Iterable(如 List 或 Vector)并返回它,或者返回它的 Iterator。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-04-09
        • 1970-01-01
        • 2015-09-19
        • 2010-11-25
        • 2012-03-23
        • 2014-03-25
        • 2017-06-12
        • 2011-02-05
        相关资源
        最近更新 更多