基于泛型创建空列表<String>
Creating an empty List<String> based on Generics
所以我目前正在尝试实现一种方法,该方法对列表进行一些过滤,而不管它们的实际类型。这是实际的方法:
public static <T extends List<String>> T filterList(T list, Predicate <String> predicate) {
T newList = ???
list.forEach(s -> {
if (predicate.test(s)) newList.add(s);
});
return newList;
}
因此泛型类型 T 基本上是 List 的某些实现,例如 ArrayList 或 LinkedList,无论它们的实际实现如何,我都想通过作为参数传递的 Predicate 进行一些过滤。该方法的 return 类型与作为参数传递的列表相同。但是如何实例化一个基于 T 的空列表(见第 2 行)?
为了向您展示该方法的用途,我提供了一个示例。以下示例将根据包含字符串的长度过滤 ArrayList:
ArrayList<String> listOfNames = new ArrayList<>();
listOfNames.add("Whosebuguser");
listOfNames.add("sitaguptana");
listOfNames.add("nyan cat");
listOfNames.add("pedro");
Predicate<String> lengthUnderTen = (string) -> string.length() < 10;
ArrayList <String> result = filterList(listOfNames,lengthUnderTen);
如果您可以将您的方法修改为
public static <T> List<T> filterList(List<T> list, Predicate<T> predicate) {
return list.stream().filter(predicate).collect(Collectors.toList());
}
它看起来很干净,因为它适用于任何类型的 List,而不仅仅是 List。这种方法会更通用。
让调用者也传入 Supplier<T>
。
public static <T extends List<String>> T filterList(T list, Predicate <String> predicate, Supplier<T> listCreator) {
T newList = listCreator.get();
list.forEach(s -> {
// ...
如果我没有正确理解你的问题,那么我完全不明白你为什么需要在这里使用泛型。
以下函数将接受任何扩展列表的 class 作为参数,例如ArrayList、LinkedList 等:
public static List<String> filterList(List<String> list, Predicate<String> predicate) {
return list.stream().filter(predicate).collect(Collectors.toList());
}
完整示例:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class Example {
public static void main(String[] args) {
ArrayList<String> example1 = new ArrayList<>();
example1.add("abc");
example1.add("ghe");
LinkedList<String> example2 = new LinkedList<>();
example2.add("foo");
example2.add("bar");
List<String> result1 = filterList(example1, s -> s.contains("a"));
List<String> result2 = filterList(example2, s -> s.contains("f"));
}
public static List<String> filterList(List<String> list, Predicate<String> predicate) {
return list.stream().filter(predicate).collect(Collectors.toList());
}
}
您可以通过传递 List<String>
作为参数通过反射创建 class。
事实上,您不需要为列表指定任何通配符。
public static List<String> filterList(List<String> list, Predicate<String> predicate) throws InstantiationException, IllegalAccessException {
List<String> newList = list.getClass()
.newInstance();
list.forEach(s -> {
if (predicate.test(s)) newList.add(s);
});
return newList;
}
但请注意,如果实施无关紧要,更简洁的方法是使用流来收集新列表:
public static List<String> filterList(List<String> list, Predicate<String> predicate) throws InstantiationException, IllegalAccessException {
return list.stream()
.filter(predicate)
.collect(Collectors.toList());
}
你有一个基础 class 已经允许你干净地编程接口。您可以将此 API 方法设计为 return 一个 List
对象,将通用类型保持在元素级别。
请注意,此模式已由标准 API (List/Collection + Stream) 提供,因此您无需重新创建它。 - 请参阅底部的注释。
如果您没有关于列表类型的任何约束 return,那么它是这个实现的选择列表类型returns(使用下面的数组列表):
public static <T> List<T> filterList(List<T> list, Predicate<T> predicate) {
List<T> newList = new ArrayList<>(); //You can choose a different type here
list.forEach(s -> {
if (predicate.test(s)) newList.add(s);
});
return newList;
}
如果让调用者选择创建什么类型的列表,那么也许您应该选择一个工厂:
public static <U, T extends List<U>> T filterList(T list,
Predicate<U> predicate, Supplier<T> newListFactory) {
T newList = newListFactory.get(); //You can choose a different type here
list.forEach(s -> {
if (predicate.test(s))
newList.add(s);
});
return newList;
}
注意:集合API:
已经提供了这个模式
java.util.stream.Stream.filter(Predicate<? super T>)
这允许您做完全相同的事情,除了创建 returned 列表(例如,您 运行 collect(Collectors.toList())
)
所以我目前正在尝试实现一种方法,该方法对列表进行一些过滤,而不管它们的实际类型。这是实际的方法:
public static <T extends List<String>> T filterList(T list, Predicate <String> predicate) {
T newList = ???
list.forEach(s -> {
if (predicate.test(s)) newList.add(s);
});
return newList;
}
因此泛型类型 T 基本上是 List 的某些实现,例如 ArrayList 或 LinkedList,无论它们的实际实现如何,我都想通过作为参数传递的 Predicate 进行一些过滤。该方法的 return 类型与作为参数传递的列表相同。但是如何实例化一个基于 T 的空列表(见第 2 行)? 为了向您展示该方法的用途,我提供了一个示例。以下示例将根据包含字符串的长度过滤 ArrayList:
ArrayList<String> listOfNames = new ArrayList<>();
listOfNames.add("Whosebuguser");
listOfNames.add("sitaguptana");
listOfNames.add("nyan cat");
listOfNames.add("pedro");
Predicate<String> lengthUnderTen = (string) -> string.length() < 10;
ArrayList <String> result = filterList(listOfNames,lengthUnderTen);
如果您可以将您的方法修改为
public static <T> List<T> filterList(List<T> list, Predicate<T> predicate) {
return list.stream().filter(predicate).collect(Collectors.toList());
}
它看起来很干净,因为它适用于任何类型的 List,而不仅仅是 List
让调用者也传入 Supplier<T>
。
public static <T extends List<String>> T filterList(T list, Predicate <String> predicate, Supplier<T> listCreator) {
T newList = listCreator.get();
list.forEach(s -> {
// ...
如果我没有正确理解你的问题,那么我完全不明白你为什么需要在这里使用泛型。
以下函数将接受任何扩展列表的 class 作为参数,例如ArrayList、LinkedList 等:
public static List<String> filterList(List<String> list, Predicate<String> predicate) {
return list.stream().filter(predicate).collect(Collectors.toList());
}
完整示例:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class Example {
public static void main(String[] args) {
ArrayList<String> example1 = new ArrayList<>();
example1.add("abc");
example1.add("ghe");
LinkedList<String> example2 = new LinkedList<>();
example2.add("foo");
example2.add("bar");
List<String> result1 = filterList(example1, s -> s.contains("a"));
List<String> result2 = filterList(example2, s -> s.contains("f"));
}
public static List<String> filterList(List<String> list, Predicate<String> predicate) {
return list.stream().filter(predicate).collect(Collectors.toList());
}
}
您可以通过传递 List<String>
作为参数通过反射创建 class。
事实上,您不需要为列表指定任何通配符。
public static List<String> filterList(List<String> list, Predicate<String> predicate) throws InstantiationException, IllegalAccessException {
List<String> newList = list.getClass()
.newInstance();
list.forEach(s -> {
if (predicate.test(s)) newList.add(s);
});
return newList;
}
但请注意,如果实施无关紧要,更简洁的方法是使用流来收集新列表:
public static List<String> filterList(List<String> list, Predicate<String> predicate) throws InstantiationException, IllegalAccessException {
return list.stream()
.filter(predicate)
.collect(Collectors.toList());
}
你有一个基础 class 已经允许你干净地编程接口。您可以将此 API 方法设计为 return 一个 List
对象,将通用类型保持在元素级别。
请注意,此模式已由标准 API (List/Collection + Stream) 提供,因此您无需重新创建它。 - 请参阅底部的注释。
如果您没有关于列表类型的任何约束 return,那么它是这个实现的选择列表类型returns(使用下面的数组列表):
public static <T> List<T> filterList(List<T> list, Predicate<T> predicate) {
List<T> newList = new ArrayList<>(); //You can choose a different type here
list.forEach(s -> {
if (predicate.test(s)) newList.add(s);
});
return newList;
}
如果让调用者选择创建什么类型的列表,那么也许您应该选择一个工厂:
public static <U, T extends List<U>> T filterList(T list,
Predicate<U> predicate, Supplier<T> newListFactory) {
T newList = newListFactory.get(); //You can choose a different type here
list.forEach(s -> {
if (predicate.test(s))
newList.add(s);
});
return newList;
}
注意:集合API:
已经提供了这个模式java.util.stream.Stream.filter(Predicate<? super T>)
这允许您做完全相同的事情,除了创建 returned 列表(例如,您 运行 collect(Collectors.toList())
)