简体   繁体   English

如何使用Lambda收集列表列表中的属性值?

[英]How dep I can collect atributes values in a List of List with Lambda?

I have a Object with this structure: 我有一个具有以下结构的对象:

public class CategoryDTO {

    @JsonProperty("id")
    private Long id;

    @JsonProperty("parentId")
    private Long parentId;

    @JsonProperty("name")
    private String nameCategory;

    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    private ComissaoPadraoEntity comission;

    @JsonProperty("categories")
    private List<CategoriaDTO> subcategories;

I make this method: 我做这个方法:

public Map<Long, List<Long>> mapATreeOfCategories(List<CategoryDTO> categories) {
        Map<Long, List<Long>> treeCategories = categoires.stream()
                .collect(Collectors.toMap(c -> c.getId(),
                        v -> v.getCategories().stream()
                                .map(e -> e.getId()).collect(Collectors.toList())));
        return treeCategories;

I have two problems here, first Te returns is this: 我这里有两个问题,第一个Te返回是这样的:

"1813": [1827,1830,1839,1834,1706,1822,2239,1835,2400,3290,3355,3319],...

OBS: They only cat de firs level as a key, and the second as values. OBS:他们只将优先级作为键,将第二个键作为值。 It even considerate a third level. 它甚至考虑了第三级。

if you look at the below structure i need the returns comes this way: 如果您看下面的结构,我需要这样返回:

"1813":[1813]

"1827":[1827,1813]

"1830":[1830,1827,1813]

"1831":[1831,1830,1827,1813]



<!--Payload-->
      {
          "categories": [
            {
              "id": "1813",
              "parentId": null,
              "name": "Malas e Mochilas",
              "items": 12,
              "categories": [
                {
                  "id": "1827",
                  "parentId": "1813",
                  "name": "Conjuntos de Malas",
                  "items": 0,
                  "categories": [

                  ],
                  "attributes": null
                },
                {
                  "id": "1830",
                  "parentId": "1813",
                  "name": "Mochilas",
                  "items": 4,
                  "categories": [
                    {
                      "id": "1831",
                      "parentId": "1830",
                      "name": "Mochila Esportiva",
                      "items": 0,
                      "categories": [

                      ],

and the second one, I know this object only have three levels, but in the future if comes one more level i want to prevent this. 第二个,我知道这个对象只有三个级别,但是将来如果再有一个级别,我想防止这种情况。

I want to know if there is a way to do this method with lambda, how dep one search with lambda can go. 我想知道是否可以使用lambda进行此方法,如何使用lambda进行一次搜索。 Or the only way is with the basic for each structure ? 还是唯一的方法是使用每种结构的基础?

Thanks for any help. 谢谢你的帮助。

private void associarCategorias(List<CategoriaDTO> categorias, Map<Long, List<Long>> arvoreDeCategorias) {
        categorias.forEach(departamento -> {
            arvoreDeCategorias.put(departamento.getCodigoCategoria(), Arrays.asList(departamento.getCodigoCategoria()));

            if (!ObjectUtils.isEmpty(departamento.getSubCategorias()) || !departamento.getSubCategorias().isEmpty()) {
                departamento.getSubCategorias().forEach(categoria -> {
                    arvoreDeCategorias.put(categoria.getCodigoCategoria(),
                            Arrays.asList(categoria.getCodigoCategoria(), departamento.getCodigoCategoria()));

                    if (!ObjectUtils.isEmpty(categoria.getSubCategorias()) || !categoria.getSubCategorias().isEmpty()) {
                        categoria.getSubCategorias().forEach(subCategoria -> {
                            arvoreDeCategorias.put(subCategoria.getCodigoCategoria(),
                                    Arrays.asList(subCategoria.getCodigoCategoria(), categoria.getCodigoCategoria(), departamento.getCodigoCategoria()));
                        });
                    }
                    return;
                });
                return;
            }
            associarCategorias(departamento.getSubCategorias(), arvoreDeCategorias);
        });
    }

Basically you are looking into something that implements a deep-first traversal and then spit out the id stack as you move into the next recursion. 基本上,您正在寻找一种实现深度优先遍历的东西,然后在进入下一个递归时吐出id堆栈。 This might best implemented using a regular recursion (if not too deep) or an iterative version using Stack data-structure to keep the id stack as you move along the traversal. 最好使用常规递归(如果不太深入)或使用堆栈数据结构的迭代版本来实现,以在遍历过程中保持id堆栈。

Pseudo-code: 伪代码:

final Map<Integer, List<Integer>> categoriesMaps(final JsonNode node, final Stack<Integer> parentIds, final Map<Integer, List<Integer>> dest) {
    dest.put(node.categoryId, new ArrayList<>(parentIds));
    parentIds.push(node.categoryId)
    for (final Node child : node.children()) {
        categoriesMaps(child, parentIds, dest);
    }
    parentIds.pop(); // removes node.categoryIds
}

I don't think this is the best use of lambda/stream specially if the maximum depth is unknown at compilation time and may vary between "leafs" ID. 我认为这不是lambda / stream的最佳用法,特别是如果最大深度在编译时未知,并且在“叶子” ID之间可能有所不同。

Perhaps the best way to get this seemly done with stream is create your own Spliterator that would produced the wanted stream of LeafIds -> parentIDStackList pairs that then you can collect into a map if that is what you want. 也许用流完成此操作的最佳方法是创建自己的Spliterator,该分离器将生成所需的LeafIds-> parentIDStackList对流,然后将其收集到映射中(如果需要)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM