【问题标题】:How to iterate over List<? extends E> in Java and use the actual object?如何遍历 List<?在 Java 中扩展 E> 并使用实际对象?
【发布时间】:2021-01-02 00:26:52
【问题描述】:

所以我知道要进行迭代,我可以使用 for-each 或 Iterator。但我的问题是我想通过按条件删除一些元素来创建一个相同类型的新列表。 例如-

List<? extends E> myList;
List<? extends E> newList = new ArrayList<>();
for(E element: myList) {
   if(element.getName().equals("abc")) {
      newList.add(element); // would throw an error because the list is of a different type. 
   }
}

我该怎么做?有什么不同的方法来解决这个问题吗?

【问题讨论】:

  • 将结果声明为List&lt;? extends E&gt; newList 是没有意义的。只需使用List&lt;E&gt; newList
  • 唯一的好处是类型匹配输入。如果您需要将列表传递回您从哪里获得输入,那么 可能 是相关的。

标签: java list arraylist collections extends


【解决方案1】:

你可以这样尝试:

List<? extends E> newList = myList.stream().filter(x -> x.getName().equals("abc")).collect(Collectors.toList());

但如果您需要隐藏在“?”后面的类型那么你需要检查你的循环内部是否元素是某个类的实例,但不可能将你的元素添加到 List

所以这会起作用:

public static void main(String[] args) {
        List<? extends E> myList  = new ArrayList<>();;

        List<E> newList = new ArrayList<>();

        for(E element: myList) {
            if (element instanceof D) {
                D elementD = (D)element;
                if(elementD.getName().equals("abc")) {
                    newList.add(elementD); // would throw an error because the list is of a different type.
                }

            }
        }

    }

这也行

public static void main(String[] args) {
        List<? extends E> myList  = new ArrayList<>();;

        List<D> newList = new ArrayList<>();

        for(E element: myList) {
            if (element instanceof D) {
                D elementD = (D)element;
                if(elementD.getName().equals("abc")) {
                    newList.add(elementD); // would throw an error because the list is of a different type.
                }

            }
        }

    }

但这行不通:

public static void main(String[] args) {
        List<? extends E> myList  = new ArrayList<>();;

        List<? extends E> newList = new ArrayList<>();

        for(E element: myList) {
            if (element instanceof D) {
                D elementD = (D)element;
                if(elementD.getName().equals("abc")) {
                    newList.add(elementD); // would throw an error because the list is of a different type.
                }

            }
        }

    }

【讨论】:

    【解决方案2】:

    您不能将任何非null 值添加到List&lt;? extends E&gt;,因为编译器无法验证该类型是否与未知类型匹配。

    您需要告诉编译器这两个列表实际上属于同一类型才能允许这样做。您可以通过将代码提取到单独的方法来做到这一点:

    List<? extends E> myList;
    List<? extends E> newList = filterList(myList);
    ...
    
    private <T extends E> List<T> filterList(List<T> myList) {
      List<T> newList = new ArrayList<>();
      for(T element: myList) {
        if(element.getName().equals("abc")) {
            newList.add(element);
        }
      }
      return newList;
    }
    

    这样,您基本上可以“命名”匿名类型? extend E,并在方法调用期间将其称为T。现在编译器知道你在做什么是合法的。

    【讨论】:

    • 但是获得List&lt;? extends E&gt; 作为结果没有任何优势。 List&lt;? extends E&gt; 没有任何事情可以用 List&lt;E&gt; 做。
    【解决方案3】:

    我做了类似的事情

    mylist.removeIf(element -> element.getName().equals("abc"));
    

    【讨论】:

      猜你喜欢
      • 2015-06-17
      • 2013-12-28
      • 1970-01-01
      • 2019-10-29
      • 2015-02-27
      • 1970-01-01
      • 1970-01-01
      • 2019-04-15
      • 2016-03-09
      相关资源
      最近更新 更多