【问题标题】:How to modify objects in a List<? extends MyObject> while iterating?如何修改列表中的对象<?迭代时扩展 MyObject>?
【发布时间】:2019-01-11 07:36:57
【问题描述】:

我正在尝试修改 List 中选择对象中的字段,但我无法使用普通 Iterator 找到这样做的方法,因为它没有 set() 方法。

我尝试使用提供set() 方法的ArrayListIterator,但这会引发转换异常。有没有办法解决这个问题?

   Iterator it = topContainer.subList.iterator();
   while (it.hasNext()) {
      MyObject curObj = (MyObject) it.next();
      if ( !curObj.getLabel().contains("/") ) {
           String newLabel = curObj.getLabel() + "/";
           curObj.setLabel(newLabel);
           ((ArrayListIterator) it).set(curObj)
       }
    }

我希望列表中的原始当前对象可以顺利设置,但我得到了这个异常:

java.util.ArrayList$itr 不能转换为 org.apache.commons.collections.iterators.ArrayListIterator

完成我想做的事情的正确方法是什么?

【问题讨论】:

  • curObj.setLabel(newLabel); 应该足够了。您想要的只是更改对象上的标签,您不需要在列表中用自身覆盖对象
  • MyObject 类有字段标签的设置器吗? setLabel ?
  • 你想达到什么目的?您可以遍历数组列表并修改对象。您不需要将对象设置为迭代器
  • @ernest_k 您的建议仅修改通过迭代器从列表中获取的原始对象的副本。我不会修改原来的。
  • @Introspective 它确实修改了原件。 MyObject 是一堂课吧?

标签: java iteration listiterator


【解决方案1】:

您根本不需要致电set。你可以在curObj上拨打setLabel:

// please, don't use raw types!
Iterator<? extends MyObject> it = topContainer.subList.iterator();
while (it.hasNext()) {
   MyObject curObj = it.next();
   if ( !curObj.getLabel().contains("/") ) {
       String newLabel = curObj.getLabel() + "/";
       curObj.setLabel(newLabel);
   }
}

【讨论】:

  • 你是对的。我根本不需要打电话给set。修改适用于原始对象。我可能错过了Iterator&lt;? extends MyObject&gt; it,这导致了一个不同的异常被抛出,这让我很困惑。谢谢。
【解决方案2】:

正确的方法如下(不适用于 1.5 以下的 java 版本):

for(MyObject curObj : topContainer.subList){
    if (!curObj.getLabel().contains("/")) {
       String newLabel = curObj.getLabel() + "/";
       curObj.setLabel(newLabel);
    }
}

这是一个增强的for循环,它也调用了迭代器,但是你看不到它。

也不需要通过迭代器设置对象,因为您在 Java 中使用对 Objects 的引用,当您编辑对象时,每个拥有指向该对象的指针的人也会看到更改。有关更多信息,您可以阅读这篇精彩的帖子:Is Java “pass-by-reference” or “pass-by-value”?

如果您不能使用 Java 5,那么您将错失良机。当前的 java 版本是 11。所以你应该真的,真的,真的,升级你的JDK

【讨论】:

    【解决方案3】:

    您只需要设置标签。在 JAVA 11 中,您可以使用流。它使您的代码更具可读性。

    List<MyObject> list = topContainer.subList;
    list
        .stream()
        .filter(Predicate.not(e->e.getLabel().contains("/")))
        .forEach(e->e.setLabel(e.getLabel()+"/"));
    

    在 java 8 中你可以使用

    (!e-&gt;e.getLabel().contains("/"))

    而不是

    Predicate.not(e-&gt;e.getLabel().contains("/")

    【讨论】:

    • 为什么不直接使用topContainer.subList.stream()?不需要Iterable 也不需要StreamSupport
    • Lino 说了什么。另外,如果你真的想要一个迭代器,为什么不直接it.forEachRemaining?
    • 还有Predicate.not不是JDK8的,那是从哪里来的?
    • @Lino 它来自 Java 11。如果您使用的是 Java 8,则可以使用 !e-&gt;e.getLabel().contains("/")。
    • 宁可e-&gt;!e.getLabel().contains("/")
    猜你喜欢
    • 2017-12-05
    • 1970-01-01
    • 2011-03-31
    • 2014-09-17
    • 2020-07-28
    • 2020-05-04
    • 2019-04-04
    相关资源
    最近更新 更多