简体   繁体   中英

How to iterate over List<? extends E> in Java and use the actual object?

So I know that to iterate I can use either for-each or Iterator. But my problem is that I want to create a new list of the same type by removing some of the elements by a condition. For ex-

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. 
   }
}

How do I go about it? Is there any different way to tackle this?

You can try like that:

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

But if you need type that is hidden behind "?" then you will need to check inside your loop if element is an instance of certain class but it is not possible to add your element into List<? extends E>

So this will work:

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.
                }

            }
        }

    }

This also will work

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.
                }

            }
        }

    }

But this won't work:

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.
                }

            }
        }

    }

You can't add any non- null values to a List<? extends E> List<? extends E> , because the compiler can't verify that the type matches the unknown type.

You'd need to tell the compiler that the two lists are actually of the same type to allow that. You can do that by extracting the code to a separate method:

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;
}

This way you basically "name" the anonymous type ? extend E ? extend E and call it T for the duration of the method call. Now the compiler knows that what you're doing is legit.

我做了类似的事情

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM