从自定义arraylist创建一个新列表
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从自定义arraylist创建一个新列表相关的知识,希望对你有一定的参考价值。
我有一个List学生,班级为Student,变量为Int studentId,String name,Boolean fullTime。
我想过滤并创建一个新列表,其中列出了我已经拥有的List学生的全职学生名称(其中fullTime为True)。
我认为最简单的方法
List<String> filteredNames = new ArrayList<>();
for(Student student : listStudents) {
if(student.isFulltime()) {
filteredNames.add(student.getName());
}
}
private class Student{
int studentID;
String name;
boolean fulltime = false;
public Student(int studentID, String name, boolean fulltime) {
this.studentID = studentID;
this.name = name;
this.fulltime = fulltime;
}
public boolean getFullTime() {
return fulltime;
}
}
private ArrayList<Student> getFullTimeStudents(ArrayList<Student> arrayList) {
ArrayList<Student> fulltimeStudents = new ArrayList<Student>();
for (Student student : arrayList) {
if (student.getFullTime()) {
fulltimeStudents.add(student);
}
}
return fulltimeStudents;
}
其他答案肯定更短,并将使用最少的代码行完成工作。但更普遍地考虑这个问题很有意思。我越来越喜欢采用功能性方法。如果从功能方法中查看问题,则需要执行两个基本操作。首先,您需要获取一种类型的列表并将其转换为另一种类型的列表。此操作称为map。然后,您希望根据某些条件生成包含该列表子集的另一个列表。这称为过滤器。有许多库向Java添加功能类型操作,如Guava,Java 8将这些操作直接添加到集合中。但是对于一个简单而肮脏的例子,你可以在Java 7中自己做(可以在android上运行):
首先,我创建一个名为Lists的静态助手类。函数的基本思想是获取一个或多个输入并产生输出。所以我们定义一个函数,它可以接受某种类型的输入并产生一些其他类型的输出。我们尽可能地通用:
public interface Func1<T, R> {
R call(T t1);
}
call()是你如何使用这个功能。它被称为Func1,因为它需要1个输入。您可以创建任意数量的接受多个输入的函数,但在您的情况下,我们只需要Func1。 Func2看起来像这样,例如:
public interface Func2<T1, T2, R> {
R call(T1 t1, T2 t2);
}
等等。
因此,在您的情况下,您希望将地图和过滤器应用于您的学生列表。您可以按任何顺序应用它们,但对我来说,过滤然后映射是有意义的。
所以这是过滤操作:
public static <T> List<T> filter(List<T> orig, Func1<? super T, Boolean> func) {
List<T> ret = new ArrayList<>();
for(T obj : orig) {
if(func.call(obj)) {
ret.add(obj);
}
}
return ret;
}
这是以更通用的方式完成其他人所建议的相同工作。满足函数调用方法中定义的条件的任何内容都将添加到返回的列表中。
最后我们有地图:
public static <T1, T2> List<T2> map(List<T1> orig, Func1<? super T1, T2> mapFunc) {
List<T2> ret = new ArrayList<>();
for(T1 obj : orig) {
ret.add(mapFunc.call(obj));
}
return ret;
}
同样,这只是以前答案的通用版本。所有工作都将在您定义的mapFunc的调用方法中进行。
所以完整的类看起来像这样:
class Lists {
public interface Func1<T, R> {
R call(T t1);
}
public static <T> List<T> filter(List<T> orig, Func1<? super T, Boolean> func) {
List<T> ret = new ArrayList<>();
for(T obj : orig) {
if(func.call(obj)) {
ret.add(obj);
}
}
return ret;
}
public static <T1, T2> List<T2> map(List<T1> orig, Func1<? super T1, T2> mapFunc) {
List<T2> ret = new ArrayList<>();
for(T1 obj : orig) {
ret.add(mapFunc.call(obj));
}
return ret;
}
}
你像这样使用它:
// students is List<Student>
List<Student> filteredStudents = Lists.filter(students, new Func1<Student, Boolean>() {
@Override
public Boolean call(Student s) {
return s.getFullTime();
}
});
List<String> filteredNames = Lists.map(filteredStudents, new Func1<Student, String>() {
@Override
public String call(Student s) {
return s.getName();
}
});
在Java中执行此操作非常冗长,但概念很有趣。 Java 8内置了很多这些概念并使用了闭包,因此输入的次数要少得多。如果您对此感兴趣,您还应该查看RxJava,它确实开辟了新的可能性,我发现它非常适合Android,其中大量工作用于执行异步操作。
以上是关于从自定义arraylist创建一个新列表的主要内容,如果未能解决你的问题,请参考以下文章
如何从自定义列表视图中获取选定项目并在 toast 消息中打印?
从自定义列表 Xamarin 中设置所选列表视图项的背景颜色