我正在为大学的家庭作业不允许我改变类的属性。我为搜索方法提出了以下代码,但我不禁注意到重复的代码。我需要建立两种搜索方法。一种搜索ArrayList<Person>
,另一种搜索ArrayList<Module
。 Person
和Module
都具有String name
属性。
public static <T extends Person> ArrayList<T> findPerson(List<T> list, String query) {
ArrayList<T> matching = new ArrayList<>();
list.forEach(s -> {
if (s.name.contains(query)) matching.add(s);
});
return matching;
}
public static <T extends Module> ArrayList<T> findModule(List<T> list, String query) {
ArrayList<T> matching = new ArrayList<>();
list.forEach(s -> {
if (s.name.contains(query)) matching.add(s);
});
return matching;
}
是否可以在不更改类结构的情况下组合这些方法?我想沿着这些线路的东西,但它仍然不似乎工作:(在方法签名不同的类型参数)
public static <T extends Person, Module> ArrayList<T> findModule(List<T> list, String query) {
ArrayList<T> matching = new ArrayList<>();
list.forEach(s -> {
if (s.name.contains(query)) matching.add(s);
});
return matching;
}
编辑:以下是这些类:
public abstract class Person extends TableItem {
public String name, famName, street, zip, city;
public String[] data = new String[7];
...
}
public class Module extends TableItem {
private Manager manager;
public String[] data = new String[5];
public String name, nr, profID, semester, part;
public ArrayList<String> participants;
...
}
public abstract class TableItem {
public abstract String getString();
public abstract void updateData();
}
答案 0 :(得分:3)
理想地,您使两个类都实现相同的接口,例如将具有功能NamedItem
的{{1}},因为要使函数采用getName()
,所以它要简单得多。如果无法做到这一点,则必须提供List<? extends NamedItem>
来确定要匹配的Function
属性。
String
然后您可以像使用它一样
public static <T> List<T> find(List<T> list, String query, Function<T, String> keyExtractor) {
return list
.stream()
.filter(s -> keyExtractor.apply(s).contains(query))
.collect(Collectors.toList());
}
您可以将其与任何属性一起使用,而不仅仅是名称。您只需传递提取要匹配的List<Person> matchingPersons = find(allPersons, query1, Person::getName);
List<Module> matchingModules = find(allModules, query1, Module::getName);
作为第三个参数的函数即可。
答案 1 :(得分:2)
为泛型类型指定多个基本类型的唯一方法是使用&
语法:
<T extends Person & Module>
但是在这种情况下,T
必须同时扩展两者,所以这不是您要的内容。
要结合使用这两种方法,这些类型必须共享一个公共接口,例如
public interface Named {
String getName();
}
现在,如果Person
和Module
都扩展/实现了Named
接口,则您的方法可以是:
public static <T extends Named> ArrayList<T> findNamed(List<T> list, String query) {
return list.stream().filter(s -> s.getName().contains(query))
.collect(Collectors.toCollection(ArrayList::new));
}