英文:
How to iterate over List<? extends E> in Java and use the actual object?
问题
我知道可以使用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); // 会引发错误,因为列表是不同类型的。
}
}
我该怎么做?有没有其他不同的方法来解决这个问题?
英文:
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?
答案1
得分: 2
你可以尝试这样做:
List<? extends E> newList = myList.stream().filter(x -> x.getName().equals("abc")).collect(Collectors.toList());
但是,如果你需要访问在"?"后面隐藏的类型,那么你需要在循环内部检查元素是否是某个特定类的实例,但是不可能将你的元素添加到 List<? extends E>
中。
因此,下面这个示例会起作用:
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); // 会抛出错误,因为列表的类型不同。
}
}
}
}
这个也会起作用:
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); // 会抛出错误,因为列表的类型不同。
}
}
}
}
但是这个不会起作用:
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); // 会抛出错误,因为列表的类型不同。
}
}
}
}
英文:
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.
}
}
}
}
答案2
得分: 0
你不能向List<? extends E>
中添加任何非null
值,因为编译器无法验证类型是否与未知类型匹配。
要允许这样做,你需要告诉编译器这两个列表实际上是相同类型的。你可以通过将代码提取到一个单独的方法中来实现:
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
。现在编译器知道你所做的是合法的。
英文:
You can't add any non-null
values to a 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
and call it T
for the duration of the method call. Now the compiler knows that what you're doing is legit.
答案3
得分: 0
我做了类似这样的事情:
mylist.removeIf(element -> element.getName().equals("abc"));
英文:
I did something like
mylist.removeIf(element -> element.getName().equals("abc"));
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论