我有一个对象列表,我想从符合特定标准的对象开始迭代子列表。
(具体地说,是一个类的声明字段列表,从字段开始,如名称而不是整数索引。)
显然,一个解决方案是迭代整个列表,在找到特定对象时设置一个标志,但是我想知道Java 8是否改进了对高阶编程的支持,提供了更优雅的这样做的方法。
在Java 8中,最优雅/惯用的方法是什么? (性能不是考虑因素;有问题的代码只能在每次执行程序时运行一次。)
答案 0 :(得分:1)
使用Guava,您可以
// list is an instance of List<T> from which the sublist is wanted
Iterable<T> sublist = Iterables.skip(list, list.indexOf(certainObject));
但是,这不使用Java 8的任何新功能。
答案 1 :(得分:1)
你可以:
List<T> list = ...;
Optional<T> first = list.stream()
.filter(f -> f.name.equals("field name"))
.findFirst();
return first.isPresent()
? list.subList(list.indexOf(first))
: Collections.emptyList();
ps:在移动设备上,所以不确定它是否会编译,但总体思路应该有效。
答案 2 :(得分:1)
您似乎希望indexOf
方法充当谓词,您可以在其中提供自定义属性来判断您是否找到满足它的第一个对象。
可以使用辅助方法完成。
static <T> List<T> getSubList(List<T> list, Predicate<T> pred){
return list.subList(list.indexOf(list.stream().filter(pred).findFirst().get()), list.size());
}
它的作用是:
Stream<T>
Optional<T>
来电get()
indexOf
来获取此对象的索引sublist
然后你可以这样称呼它;
List<MyClass> subList = getSubList(list, o -> o.b.startsWith("10"));
对于一个小例子,这里是如何从第一个对象获取子列表,其中String值以10开头,直到列表末尾。
public class Test {
public static void main(String[] args) {
List<MyClass> list = new ArrayList<>();
for(int i = 0; i < 15; i++){
list.add(new MyClass(i, String.valueOf(i)));
}
System.out.println(getSubList(list, o -> o.s.startsWith("10"))); //[MyClass [a=10, b=10], MyClass [a=11, b=11], MyClass [a=12, b=12], MyClass [a=13, b=13], MyClass [a=14, b=14]]
}
static <T> List<T> getSubList(List<T> list, Predicate<T> pred){
return list.subList(list.indexOf(list.stream().filter(pred).findFirst().get()), list.size());
}
}
class MyClass {
int i;
String s;
public MyClass(int i,String s){
this.i = i;
this.s = s;
}
@Override
public String toString() {
return "MyClass [i=" + i + ", s=" + s + "]";
}
}
您可以添加更多支票,例如,通过调用Optional
来查看您是否拥有isPresent()
(使用findFirst
)的值,但您的主要想法是:怎么做。
希望它有所帮助! :)