[英]lambda Java 8, how to map a list that is a filed of the result of filter operation
I have a catalog-like object hierarchy where every object has a name field. 我有一个类似目录的对象层次结构,其中每个对象都有一个名称字段。
class A {
List<A> list;
String name;
}
A{A{A{A...}AA},A{AAA},A{AAA}} // the depth is finite (~4)
I would like to provide a set of methods that return a list of child names (a a.getName()) of any parent element for a given name. 我想提供一组方法,返回给定名称的任何父元素的子名称列表(a.getName())。 So for level 1 I have 所以对于1级我有
a.getAs().stream().map(a1 -> a1.getName()).collect(Collectors.toList());
Level 2 I have already troubles with: 2级我已经遇到过麻烦:
a1.getAs().stream().filter(a2 -> a2.getName() == name)
now I want to access the As and map them to their names but I don't know how 现在我想访问As并将它们映射到他们的名字,但我不知道如何
EDIT: I have just realized that from the third level on it wouldn't be possible to find the list with just providing a single name. 编辑:我刚刚意识到从第三级开始就不可能只提供一个名称就能找到列表。 I would need a name for each level to be able to navigate to the node where the child list could be collected. 我需要每个级别的名称才能导航到可以收集子列表的节点。 On one hand I could keep all the objects in one Set and access them with an id. 一方面,我可以将所有对象保存在一个Set中,并使用id访问它们。 They would still have references to each other. 他们仍然会互相引用。 On the other hand by not knowing the root element I couldn't get the structure right. 另一方面,由于不知道根元素,我无法使结构正确。
I think I have to rethink the problem. 我想我必须重新思考这个问题。
It works only for one level of the hierarchy: 它仅适用于层次结构的一个级别:
public List<A> getSubcategoriesByParentName(A category, String name) {
return category.getSubcategories()
.stream()
.filter(subcategory -> subcategory.getName().equals(name))
.collect(Collectors.toList());
}
To achieve the next level, you could use a flatMap
: 要实现下一个级别,您可以使用flatMap
:
category.getSubcategories().stream()
.flatMap(s -> s.getSubcategories().stream())
.filter(s -> s.getName().equals(name))
.collect(Collectors.toList());
As you can see, there is a need of recursion, it is not a work for Stream API. 如您所见,需要递归,它不适用于Stream API。
Of course, being aware of the depth, we could access to all levels (by using a flatMap(s -> s.getSubcategories().stream())
several times), but it will look ugly. 当然,在意识到深度之后,我们可以访问所有级别(通过使用flatMap(s -> s.getSubcategories().stream())
几次),但它看起来很难看。
You can do it like this: 你可以这样做:
public static List<String> getChildNames(A node, String... path) {
Stream<A> s = node.getAs().stream();
for(String name: path)
s = s.filter(a -> a.getName().equals(name)).flatMap(a -> a.getAs().stream());
return s.map(A::getName).collect(Collectors.toList());
}
but if the names beneath an A
node are unique, you should consider maintaining a Map<String,A>
, mapping from child name to actual child, instead of a List<A>
. 但是如果A
节点下的名称是唯一的,则应考虑维护Map<String,A>
,从子名称到实际子项的映射,而不是List<A>
。 That would make traversing a path via unique name/ID as simple as node.get(name1).get(name2)
. 这将通过唯一的名称/ ID遍历路径,就像node.get(name1).get(name2)
一样简单。 The logic of the method above would still be useful if you incorporate pattern matching, which doesn't need to have a unique result. 如果您合并模式匹配,则上述方法的逻辑仍然有用,模式匹配不需要具有唯一结果。
public static List<String> getChildNames(A node, String... pathPatterns) {
Stream<A> s = node.getAs().stream();
for(String namePattern: pathPatterns) {
Pattern compiledPattern = Pattern.compile(namePattern);
s = s.filter( a -> compiledPattern.matcher(a.getName()).find())
.flatMap(a -> a.getAs().stream());
}
return s.map(A::getName).collect(Collectors.toList());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.