简体   繁体   English

lambda Java 8,如何映射一个列表,该列表是过滤操作的结果字段

[英]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.

相关问题 如何通过Java 8 Lambda在列表中使用地图过滤器 - How to use Map filter in list by Java 8 lambda Java Lambda:使用 findFirst/ifPresentOrElse 快速检查过滤器和 map 是否为结果变量的 0 或 1 - Java Lambda: Quickly check if 0 or 1 result from Filter and map to result variable, using findFirst/ifPresentOrElse 如何使用Java 8流按列表过​​滤地图? - How to filter Map by a List using Java 8 stream? 如何在Java 8中的lambda过滤器流中迭代列表? - How to iterate list inside a lambda filter stream in Java 8? 如何使用java 8 lambda和streams对Map <YearMonth,List <LocalDate >>进行排序 - How to sort Map<YearMonth, List<LocalDate>> with java 8 lambda and streams 在使用Java Lambda(如Map)时,如何在group-2中使用group-1结果key1 <key1, Map<key2, List<Obj> &gt;&gt; - How to use group-1 result key1 in group-2 when use Java Lambda like Map<key1, Map<key2, List<Obj>>> 列表过滤器中的Java 8 Lambda列表 - Java 8 lambda list inside list filter 如何使用使用.map lambda表达式的操作每次使用与列表不同的值? - How do I apply an operation using .map lambda expression using a different value from a list each time? 用于映射<Int,List <String >>的Java 8 Lambda列表 - Java 8 Lambda List to Map<Int, List<String>> Java 8 lambda错误:通过减少过滤器集合过滤流然后收集映射 - Java 8 lambda error: filter stream by reduced filter collection THEN map THEN collect
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM